<!-- Vue组件 -->
<template>
  <div class="cesiumContainerBox">
    <div id="cesiumContainer" style="width: 100%; height: 91vh"></div>
    <!-- 右键菜单 -->
    <div
      v-show="contextMenuVisible"
      class="cesium-context-menu"
      :style="contextMenuStyle"
    >
      <div class="menu-header">
        <h4>目标显示控制</h4>
        <button class="close-btn" @click="closeContextMenu">
          <i class="el-icon-close"></i>
        </button>
      </div>

      <div class="menu-section">
        <h5>通道选择</h5>
        <div class="channel-list">
          <div
            v-for="channel in channels"
            :key="channel.id"
            class="channel-item"
            @click="openChannelMenu(channel)"
          >
            <div class="channel-info">
              <el-checkbox
                v-model="channel.visible"
                @click.native.stop
                @change="toggleChannel(channel.id)"
              ></el-checkbox>
              <span class="channel-name">{{ channel.name }}</span>
              <el-tag size="mini" :type="channel.active ? 'success' : 'info'">
                {{ channel.active ? "已激活" : "未激活" }}
              </el-tag>
              <i class="el-icon-arrow-right channel-arrow"></i>
            </div>
          </div>
        </div>
      </div>

      <div class="menu-divider"></div>

      <div class="menu-section action-buttons">
        <el-button type="success" size="small" @click="showAllTargets">
          <i class="el-icon-view"></i> 显示所有目标
        </el-button>
        <el-button type="danger" size="small" @click="hideAllTargets">
          <i class="el-icon-hide"></i> 隐藏所有目标
        </el-button>
      </div>
    </div>

    <!-- 通道操作菜单 -->
    <div
      v-show="channelMenuVisible"
      class="channel-operation-menu"
      :style="channelMenuStyle"
    >
      <div class="menu-header">
        <h4>{{ currentChannel.name }} 操作</h4>
        <button class="close-btn" @click="channelMenuVisible = false">
          <i class="el-icon-close"></i>
        </button>
      </div>
      <!-- 电离层专用操作 -->
      <div v-if="currentChannel.type === 'ionosphere'" class="menu-section">
        <el-button
          class="menu-btn"
          @click="toggleChannelVisibility(currentChannel.id)"
        >
          <i class="el-icon-video-play"></i>
          {{ currentChannel.visible ? "隐藏通道" : "显示通道" }}
        </el-button>

        <el-checkbox
          v-model="currentChannel.showFrequency"
          class="frequency-checkbox"
        >
          显示频率标签
        </el-checkbox>
      </div>
      <div v-else>
        <div class="menu-section">
          <el-button
            class="menu-btn"
            @click="toggleChannelVisibility(currentChannel.id)"
          >
            <i class="el-icon-video-play"></i>
            {{ currentChannel.visible ? "隐藏通道" : "显示通道" }}
          </el-button>

          <el-button
            class="menu-btn"
            @click="openColorConfig(currentChannel.id)"
          >
            <i class="el-icon-brush"></i>
            颜色配置
          </el-button>

          <el-button
            class="menu-btn"
            @click="openFilterConfig(currentChannel.id)"
          >
            <i class="el-icon-filter"></i>
            筛选配置
          </el-button>

          <el-button
            class="menu-btn"
            @click="openAttributeConfig(currentChannel.id)"
          >
            <i class="el-icon-setting"></i>
            属性项配置
          </el-button>

          <el-button
            class="menu-btn"
            @click="openStyleConfig(currentChannel.id)"
          >
            <i class="el-icon-magic-stick"></i>
            样式配置
          </el-button>
        </div>
      </div>

      <div class="menu-divider"></div>

      <div class="menu-section action-buttons">
        <el-button
          type="primary"
          size="small"
          @click="saveChannelConfig(currentChannel.id)"
        >
          <i class="el-icon-folder-checked"></i> 保存配置
        </el-button>
        <el-button size="small" @click="channelMenuVisible = false">
          <i class="el-icon-close"></i> 关闭
        </el-button>
      </div>
    </div>

    <!-- 信息弹窗 -->
    <div v-if="infoWindowVisible" class="info-window" :style="windowStyle">
      <div class="info-header">
        <h4>航迹信息</h4>
        <button @click="closeInfoWindow" class="close-btn">
          <i class="el-icon-close"></i>
        </button>
      </div>
      <div class="info-content" v-if="selectedBatch">
        <div v-for="prop in labelProperties" :key="prop" class="info-item">
          <label>{{ getPropertyLabel(prop) }}：</label>
          <span>{{ getPropertyValue(selectedBatch, prop) }}</span>
        </div>
      </div>
    </div>

    <!-- 筛选弹窗 -->
    <el-dialog
      :title="currentChannel.name + ' 筛选配置'"
      :modal="false"
      :show-close="true"
      @mousedown.native="starDragFilter"
      :style="dialogStyle"
      :visible.sync="filterDialogVisible"
      width="600px"
      custom-class="filter-dialog"
      @closed="applyFilters"
    >
      <div class="filter-container">
        <!-- 保留属性 -->
        <div class="filter-group">
          <h4>保留属性</h4>
          <el-radio-group v-model="filters.reservedAttributes">
            <el-radio label="all">全部</el-radio>
            <el-radio label="retained">保留目标</el-radio>
            <el-radio label="unretained">未保留</el-radio>
          </el-radio-group>
        </div>
        <!-- 上报属性 -->
        <div class="filter-group">
          <h4>上报属性</h4>
          <el-radio-group v-model="filters.reportingAttributes">
            <el-radio label="all">全部</el-radio>
            <el-radio label="reported">已上报</el-radio>
            <el-radio label="unreported">未上报</el-radio>
          </el-radio-group>
        </div>
        <!-- 重点属性 -->
        <div class="filter-group">
          <h4>重点属性</h4>
          <el-checkbox-group v-model="filters.keyAttributes">
            <el-checkbox label="重点目标"></el-checkbox>
            <el-checkbox label="非重点目标"></el-checkbox>
          </el-checkbox-group>
        </div>
        <!-- 目标类型 -->
        <div class="filter-group">
          <h4>目标类型</h4>
          <el-checkbox-group v-model="filters.targetTypes">
            <el-checkbox label="对空"></el-checkbox>
            <el-checkbox label="对海"></el-checkbox>
            <el-checkbox label="对弹"></el-checkbox>
          </el-checkbox-group>
        </div>
        <!-- 敌我属性 -->
        <div class="filter-group">
          <h4>敌我属性</h4>
          <el-checkbox-group v-model="filters.allegiance">
            <el-checkbox label="敌我"></el-checkbox>
            <el-checkbox label="我机"></el-checkbox>
            <el-checkbox label="友机"></el-checkbox>
            <el-checkbox label="中立"></el-checkbox>
            <el-checkbox label="不明"></el-checkbox>
          </el-checkbox-group>
        </div>

        <!-- 操作按钮 -->
        <div class="action-btns">
          <el-button @click="resetFilters">重置</el-button>
          <el-button type="primary" @click="applyFilters">应用</el-button>
        </div>
      </div>
    </el-dialog>

    <!-- 颜色配置弹窗 -->
    <el-dialog
      :title="currentChannel.name + ' 颜色配置'"
      :modal="false"
      :show-close="false"
      @mousedown.native="startDragColorConfig"
      @mouseup.native="stopDragColorConfig"
      @mousemove.native="doDragColorConfig"
      :style="colorConfigDialogStyle"
      :visible.sync="colorConfigVisible"
      width="800px"
      custom-class="color-config-dialog"
      @closed="closeColorConfig"
    >
      <div class="color-config-container">
        <!-- 着色依据选择 -->
        <div class="color-by-section">
          <h4>着色依据：</h4>
          <el-radio-group v-model="colorConfig.colorBy" size="medium">
            <el-radio-button label="allegiance">敌我属性</el-radio-button>
            <el-radio-button label="reporting">上报属性</el-radio-button>
            <el-radio-button label="keyAttribute">重点属性</el-radio-button>
            <el-radio-button label="targetType">目标类型</el-radio-button>
            <el-radio-button label="reserved">保留属性</el-radio-button>
          </el-radio-group>
        </div>

        <!-- 颜色配置区域 -->
        <div class="color-config-grid">
          <!-- 敌我属性配置 -->
          <div
            class="color-category"
            v-show="colorConfig.colorBy === 'allegiance'"
          >
            <h4>敌我属性颜色配置：</h4>
            <div
              class="color-item"
              v-for="(label, key) in allegianceOptions"
              :key="key"
              @click="changeColorItemHandle(label, key)"
            >
              <span class="color-label">{{ label }}</span>
              <div class="color-picker-container">
                <el-color-picker
                  v-model="colorConfig.allegiance[key]"
                  show-alpha
                  :predefine="predefineColors"
                />
                <span class="color-value">{{
                  colorConfig.allegiance[key] || "#FFFFFF"
                }}</span>
              </div>
            </div>
          </div>

          <!-- 上报属性配置 -->
          <div
            class="color-category"
            v-show="colorConfig.colorBy === 'reporting'"
          >
            <h4>上报属性颜色配置：</h4>
            <div
              class="color-item"
              v-for="(label, key) in reportingOptions"
              :key="key"
            >
              <span class="color-label">{{ label }}</span>
              <div class="color-picker-container">
                <el-color-picker
                  v-model="colorConfig.reporting[key]"
                  show-alpha
                  :predefine="predefineColors"
                />
                <span class="color-value">{{
                  colorConfig.reporting[key] || "#FFFFFF"
                }}</span>
              </div>
            </div>
          </div>

          <!-- 重点属性配置 -->
          <div
            class="color-category"
            v-show="colorConfig.colorBy === 'keyAttribute'"
          >
            <h4>重点属性颜色配置：</h4>
            <div
              class="color-item"
              v-for="(label, key) in keyAttributeOptions"
              :key="key"
            >
              <span class="color-label">{{ label }}</span>
              <div class="color-picker-container">
                <el-color-picker
                  v-model="colorConfig.keyAttribute[key]"
                  show-alpha
                  :predefine="predefineColors"
                />
                <span class="color-value">{{
                  colorConfig.keyAttribute[key] || "#FFFFFF"
                }}</span>
              </div>
            </div>
          </div>

          <!-- 目标类型配置 -->
          <div
            class="color-category"
            v-show="colorConfig.colorBy === 'targetType'"
          >
            <h4>目标类型颜色配置：</h4>
            <div
              class="color-item"
              v-for="(label, key) in targetTypeOptions"
              :key="key"
            >
              <span class="color-label">{{ label }}</span>
              <div class="color-picker-container">
                <el-color-picker
                  v-model="colorConfig.targetType[key]"
                  show-alpha
                  :predefine="predefineColors"
                />
                <span class="color-value">{{
                  colorConfig.targetType[key] || "#FFFFFF"
                }}</span>
              </div>
            </div>
          </div>

          <!-- 保留属性配置 -->
          <div
            class="color-category"
            v-show="colorConfig.colorBy === 'reserved'"
          >
            <h4>保留属性颜色配置：</h4>
            <div
              class="color-item"
              v-for="(label, key) in reservedOptions"
              :key="key"
            >
              <span class="color-label">{{ label }}</span>
              <div class="color-picker-container">
                <el-color-picker
                  v-model="colorConfig.reserved[key]"
                  show-alpha
                  :predefine="predefineColors"
                />
                <span class="color-value">{{
                  colorConfig.reserved[key] || "#FFFFFF"
                }}</span>
              </div>
            </div>
          </div>
        </div>

        <!-- 操作按钮 -->
        <div class="action-btns">
          <el-button @click="resetColorConfig">重置</el-button>
          <el-button @click="closeColorConfig">取消</el-button>
          <el-button type="primary" @click="applyColorConfig">应用</el-button>
        </div>
      </div>
    </el-dialog>

    <!-- 配置弹窗 -->
    <el-dialog
      :title="currentChannel.name + ' 属性项配置'"
      :visible.sync="showTransferDialog"
      width="60%"
      top="5vh"
      custom-class="transfer-dialog"
    >
      <div class="transfer-config-dialog">
        <div class="transfer-header">
          <div class="transfer-col">
            <h4>标牌属性</h4>
            <p>点击航迹时显示的属性</p>
          </div>
          <div class="transfer-col">
            <h4>所有属性</h4>
            <p>可配置的属性列表</p>
          </div>
          <div class="transfer-col">
            <h4>表格属性</h4>
            <p>监控列表中显示的属性</p>
          </div>
        </div>

        <div class="three-column-transfer">
          <!-- 标牌属性 -->
          <div class="transfer-column">
            <div class="transfer-list">
              <div
                v-for="prop in labelProperties"
                :key="prop"
                class="transfer-item"
                @click="selectedLabelProp = prop"
                :class="{ selected: selectedLabelProp === prop }"
              >
                {{ getPropertyLabel(prop) }}
              </div>
            </div>
          </div>

          <!-- 操作按钮 - 标牌属性与所有属性之间 -->
          <div class="transfer-actions">
            <div class="btn-group">
              <el-button
                @click="addToLabels"
                icon="el-icon-arrow-left"
                circle
              ></el-button>
              <el-button
                @click="removeFromLabels"
                icon="el-icon-arrow-right"
                circle
              ></el-button>
            </div>
          </div>

          <!-- 所有属性 -->
          <div class="transfer-column">
            <div class="transfer-list">
              <div
                v-for="prop in availableProperties"
                :key="prop.key"
                class="transfer-item"
                @click="selectedProp = prop.key"
                :class="{ selected: selectedProp === prop.key }"
              >
                {{ prop.label }}
              </div>
            </div>
          </div>

          <!-- 操作按钮 - 所有属性与表格属性之间 -->
          <div class="transfer-actions">
            <div class="btn-group">
              <el-button
                @click="addToTables"
                icon="el-icon-arrow-right"
                circle
              ></el-button>
              <el-button
                @click="removeFromTables"
                icon="el-icon-arrow-left"
                circle
              ></el-button>
            </div>
          </div>

          <!-- 表格属性 -->
          <div class="transfer-column">
            <div class="transfer-list">
              <div
                v-for="prop in tableProperties"
                :key="prop"
                class="transfer-item"
                @click="selectedTableProp = prop"
                :class="{ selected: selectedTableProp === prop }"
              >
                {{ getPropertyLabel(prop) }}
              </div>
            </div>
          </div>
        </div>

        <div slot="footer" class="dialog-footer">
          <el-button @click="resetConfig">恢复默认</el-button>
          <el-button type="primary" @click="saveConfig">保存配置</el-button>
        </div>
      </div>
    </el-dialog>

    <!-- 样式配置弹窗 -->
    <el-dialog
      :title="currentChannel.name + ' 样式配置'"
      :visible.sync="styleConfigVisible"
      width="500px"
      custom-class="style-config-dialog"
      @mousedown.native="startDragStyleConfig"
      @mouseup.native="stopDragStyleConfig"
      @mousemove.native="doDragStyleConfig"
      :style="styleConfigDialogStyle"
    >
      <div class="style-config">
        <div class="config-item">
          <label>字体大小</label>
          <el-input-number
            v-model="currentStyleConfig.fontSize"
            :min="10"
            :max="24"
          ></el-input-number>
        </div>

        <div class="config-item">
          <label>字体颜色</label>
          <el-color-picker
            v-model="currentStyleConfig.fontColor"
          ></el-color-picker>
        </div>

        <!-- <div class="config-item">
          <label>背景颜色</label>
          <el-color-picker
            v-model="currentStyleConfig.backgroundColor"
            show-alpha
          ></el-color-picker>
        </div> -->
      </div>

      <div slot="footer">
        <el-button @click="styleConfigVisible = false">取消</el-button>
        <el-button type="primary" @click="applyStyleConfig">应用</el-button>
      </div>
    </el-dialog>

    <!-- 目标监控弹窗 -->
    <div
      v-show="showTargetWindow"
      class="target-monitor-window"
      :style="{ left: targetWindowPos.x + 'px', top: targetWindowPos.y + 'px' }"
      @mousedown="startDragTargetWindow"
    >
      <div class="window-header">
        <div class="tabs">
          <button
            v-for="channel in visibleChannels"
            :key="channel.id"
            :class="{ active: activeChannel === channel.id }"
            @click="activeChannel = channel.id"
          >
            {{ channel.name }} ({{ getChannelTargets(channel.id).length }})
          </button>
        </div>
        <div class="header-right">
          <el-dropdown
            trigger="click"
            @command="handleCommand"
            class="config-dropdown"
          >
            <!-- <button class="dropdown-btn">
              <i class="el-icon-setting"></i> 配置
            </button> -->
            <el-dropdown-menu slot="dropdown" class="config-menu">
              <el-dropdown-item command="a">颜色配置</el-dropdown-item>
              <el-dropdown-item command="b">筛选配置</el-dropdown-item>
              <el-dropdown-item command="c">属性项配置</el-dropdown-item>
            </el-dropdown-menu>
          </el-dropdown>
          <button class="close-btn" @click="showTargetWindow = false">
            <i class="el-icon-close"></i>
          </button>
        </div>
      </div>

      <!-- 优化虚拟列表结构 -->
      <div class="window-content">
        <div class="virtual-scroll-container" ref="scrollContainer">
          <!-- 表头容器 -->
          <div class="table-header-container" ref="headerContainer">
            <table class="target-table" :style="{ minWidth: tableMinWidth }">
              <thead>
                <tr>
                  <th
                    v-for="col in tableColumns"
                    :key="col.key"
                    :style="{ width: col.width }"
                  >
                    <div class="th-content">{{ col.label }}</div>
                  </th>
                </tr>
              </thead>
            </table>
          </div>

          <!-- 表格内容容器 -->
          <div
            class="table-body-container"
            @scroll="handleTabScroll"
            ref="bodyContainer"
          >
            <div
              class="virtual-scroll-content"
              :style="{ height: totalHeight + 'px' }"
            >
              <table class="target-table" :style="{ minWidth: tableMinWidth }">
                <tbody>
                  <tr
                    v-for="(item, index) in visibleTabData"
                    :key="item.uniqueBatchNo"
                    :class="{ selected: selectedTarget === item.uniqueBatchNo }"
                    @click="selectTarget(item)"
                    :style="getRowStyle(item, index)"
                  >
                    <td
                      v-for="col in tableColumns"
                      :key="col.key"
                      :style="{ width: col.width }"
                    >
                      {{ formatCellValue(item, col.key) }}
                    </td>
                  </tr>
                  <!-- 空数据行 -->
                  <tr v-if="visibleTabData.length === 0">
                    <td
                      :colspan="tableColumns.length"
                      style="
                        text-align: center;
                        height: 56px;
                        line-height: 56px;
                        color: #a0b9d9;
                      "
                    >
                      暂无数据
                    </td>
                  </tr>
                </tbody>
              </table>
            </div>
          </div>
        </div>
      </div>
    </div>

    <!-- 左上角控制按钮组 -->
    <div class="control-buttons">
      <button class="ctrl-btn tracklist" @click="toggleTargetWindow">
        <span class="icon">📜</span>
        <span class="label">监控</span>
      </button>
      <button class="ctrl-btn replay" @click="openReplayDrawer">
        <span class="icon">📼</span>
        <span class="label">回放</span>
      </button>
    </div>
    <!-- 航迹回放组件 -->
    <ReplayDrawer
      v-if="replayDrawerVisible"
      :visible="replayDrawerVisible"
      @close="closeReplayDrawer"
      @replay-data="handleReplayData"
      @clear-replay-tracks="clearAllTracks"
    />
  </div>
</template>

<script>
import { analysisSituation } from "@/api/map.js";
import {
  createAnnularSector,
  addSectorGrid,
  addSectorGridSmall,
} from "./utils/common";
import { WebSocketService } from "@/api/services/websocket";
import {
  PolarGridHighlighter,
  createHighlightRegions,
} from "./utils/paint_area.js";
import ReplayDrawer from "@/components/ReplayDrawer/index.vue";

const resTypeCache = new Map();
const ROW_HEIGHT = 56;
const VISIBLE_ROWS = 15;
const BUFFER_ROWS = 5;
// 通道默认配置
const defaultChannelConfig = {
  colorConfig: {
    colorBy: "allegiance",
    allegiance: {
      敌我: "#FF0000",
      我机: "#00FF00",
      友机: "#0000FF",
      中立: "#FFFF00",
      不明: "#AAAAAA",
    },
    reporting: {
      已上报: "#00FF00",
      未上报: "#FF0000",
    },
    keyAttribute: {
      重点目标: "#FF0000",
      非重点目标: "#00FF00",
    },
    targetType: {
      对空: "#FF0000",
      对海: "#0000FF",
      对弹: "#00FF00",
    },
    reserved: {
      保留目标: "#00FF00",
      未保留: "#FF0000",
    },
  },
  filterConfig: {
    targetTypes: [],
    keyAttributes: [],
    reportingAttributes: [],
    reservedAttributes: [],
    allegiance: [],
  },
  attributeConfig: {
    labelProperties: ["batchNo", "longitude", "latitude"],
    tableProperties: [
      "batchNo",
      "longitude",
      "latitude",
      "altitude",
      "speed",
      "targetType",
    ],
  },
  styleConfig: {
    fontSize: 14,
    fontColor: "#FFFFFF",
    backgroundColor: "rgba(0,0,0,0.5)",
  },
};

export default {
  components: {
    ReplayDrawer,
  },
  data() {
    return {
      replayDrawerVisible: false,
      ionosphereData: [], // 存储电离层数据
      ionosphereEntities: [], // 存储电离层实体
      // 目标数据存储结构改为按通道ID存储
      channelTargets: {
        1: [], // 雷达航迹通道 (resType=2004)
        2: [], // 综合空情通道 (resType=2007, sourceId=1)
        3: [], // ADS-B通道 (resType=2007, sourceId=2)
      },

      // 通道数据
      channels: [
        {
          id: 1,
          name: "雷达航迹通道",
          type: "radar",
          visible: true,
          active: true,
        },
        {
          id: 2,
          name: "综合空情通道",
          type: "air",
          visible: true,
          active: true,
        },
        { id: 3, name: "ADS-B通道", type: "adsb", visible: true, active: true },
        {
          id: 4,
          name: "电离层通道",
          type: "ionosphere",
          visible: true,
          active: true,
          showFrequency: true, // 控制频率标签显示
        },
      ],

      //样式配置
      isDraggingStyleConfig: false,
      dragStyleConfigStartPos: { x: 0, y: 0 },
      styleConfigDialogStartPos: { x: 300, y: 150 },
      styleConfigDialogStyle: {
        top: "150px",
        left: "300px",
        transform: "none",
      },

      // 样式配置弹窗
      styleConfigVisible: false,
      currentStyleConfig: { ...defaultChannelConfig.styleConfig },
      currentConfigChannelId: null,
      activeChannel: 1,

      // 右键菜单相关
      contextMenuVisible: false,
      contextMenuStyle: { top: "0px", left: "0px" },

      // 通道操作菜单
      channelMenuVisible: false,
      channelMenuStyle: { top: "0px", left: "0px" },
      currentChannel: {},

      // 通道配置存储
      channelConfigs: {},

      // 颜色配置弹窗相关
      colorConfigVisible: false,
      isDraggingColorConfig: false,
      dragColorConfigStartPos: { x: 0, y: 0 },
      colorConfigDialogStartPos: { x: 300, y: 100 },
      colorConfigDialogStyle: {
        top: "100px",
        left: "300px",
        transform: "none",
      },
      colorConfig: { ...defaultChannelConfig.colorConfig },
      predefineColors: [
        "#FF0000",
        "#00FF00",
        "#0000FF",
        "#FFFF00",
        "#FF00FF",
        "#00FFFF",
        "#FF4500",
        "#FF8C00",
        "#32CD32",
        "#4169E1",
        "#8A2BE2",
        "#FF1493",
        "#1E90FF",
        "#00BFFF",
        "#7CFC00",
        "#FFD700",
        "#FF69B4",
        "#9370DB",
      ],
      // 属性选项
      allegianceOptions: {
        敌我: "敌我目标",
        我机: "我机目标",
        友机: "友机目标",
        中立: "中立目标",
        不明: "不明目标",
      },
      reportingOptions: {
        已上报: "已上报目标",
        未上报: "未上报目标",
      },
      keyAttributeOptions: {
        重点目标: "重点目标",
        非重点目标: "非重点目标",
      },
      targetTypeOptions: {
        对空: "对空目标",
        对海: "对海目标",
        对弹: "对弹目标",
      },
      reservedOptions: {
        保留目标: "保留目标",
        未保留: "未保留目标",
      },

      // 筛选弹窗相关
      isDraggingFilter: false,
      dragFilterStartPos: { x: 0, y: 0 },
      filterDialogPos: { x: 200, y: 100 },
      filterDialogVisible: false,
      filters: { ...defaultChannelConfig.filterConfig },
      // 虚拟列表相关
      tableMinWidth: "100%",
      targetWindowPos: { x: 0, y: 0 },
      isDraggingTargetWindow: false,
      dragTargetStartPos: { x: 0, y: 0 }, //记录鼠标的位置
      baseProperties: [
        { key: "batchNo", label: "批次号" },
        { key: "longitude", label: "经度" },
        { key: "latitude", label: "纬度" },
        { key: "altitude", label: "高度" },
        { key: "speed", label: "速度" },
        { key: "targetType", label: "目标类型" },
        { key: "sourceId", label: "信号源" },
      ],
      dynamicProperties: [], // 动态属性（从WebSocket数据中提取）
      showTransferDialog: false,
      labelProperties: ["batchNo", "longitude", "latitude"],
      tableProperties: [
        "batchNo",
        "longitude",
        "latitude",
        "altitude",
        "speed",
        "targetType",
      ],
      selectedProp: null, // 当前选中的属性
      selectedLabelProp: null, // 当前选中的标牌属性
      selectedTableProp: null, // 当前选中的表格属性
      tableColumns: [], // 动态生成的表格列

      // 新增目标监控弹窗相关数据
      showTargetWindow: false,
      selectedTarget: null, // 当前选中的目标
      scrollTop: 0, // 当前滚动位置

      activeTab: "air", // 'air' 或 'radar'
      sectorEntities: [], //绘制小的扇环区域
      // 操控的pannel
      activeFilters: {}, // 当前生效的筛选条件
      dialogStyle: {
        top: "100px",
        left: "200px",
        transform: "none",
      },

      // 新增状态变量
      selectedBatch: null, // 当前选中的批次 { uniqueBatchNo, originalColor }
      infoWindowVisible: false, // 信息窗口显示状态
      lastKnownRotation: null,
      entities: [],
      frequenceData: null,
      wsService: null,
      viewer: null,
      initCesiumData: null,
      highlighter: null,
      entityMap: new Map(), // 存储航迹和飞机实体 { uniqueBatchNo: { polyline, plane } }
      colorMap: new Map(), // { sourceId: color }
    };
  },
  computed: {
    // 当前活动标签页数据
    currentTabData() {
      return this.getChannelTargets(this.activeChannel);
    },

    // 合并基础属性和动态属性
    allProperties() {
      return [...this.baseProperties, ...this.dynamicProperties];
    },
    // 计算可用的属性
    availableProperties() {
      return this.allProperties.filter(
        (prop) =>
          !this.labelProperties.includes(prop.key) &&
          !this.tableProperties.includes(prop.key)
      );
    },
    // 获取可见通道
    visibleChannels() {
      return this.channels.filter(
        (channel) => channel.visible && channel.type !== "ionosphere" // 排除电离层通道
      );
    },

    // 总高度计算
    totalHeight() {
      return this.currentTabData.length * ROW_HEIGHT;
    },

    startIndex() {
      return Math.max(0, Math.floor(this.scrollTop / ROW_HEIGHT) - BUFFER_ROWS);
    },

    endIndex() {
      return Math.min(
        this.startIndex + VISIBLE_ROWS + BUFFER_ROWS * 2,
        this.currentTabData.length
      );
    },

    visibleTabData() {
      const start = this.startIndex;
      const end = this.endIndex;
      return this.currentTabData.slice(start, end);
    },

    latestPosition() {
      if (!this.selectedBatch) return null;
      const entity = this.entityMap.get(this.selectedBatch.uniqueBatchNo);
      return entity?.positions?.slice(-1)[0];
    },
    windowStyle() {
      // 根据点击位置动态定位（示例简单固定在右上角）
      return {
        top: "20px",
        right: "20px",
        width: "300px",
      };
    },
  },

  mounted() {
    this.$on("clear-replay-tracks", this.clearAllTracks);
    this.initializeChannelConfigs();
    // 添加右键菜单事件监听
    this.addContextMenuListener();

    this.calculateTableWidth();
    //拖动弹窗
    this.$nextTick(() => {
      this.targetWindowPos = {
        x: (window.innerWidth - 800) / 2, // 居中
        y: (window.innerHeight - 500) / 2,
      };
    });

    //表格配置
    this.loadConfigFromLocalStorage();
    this.generateTableColumns();

    //调用websocket
    this.initWebSocket();
    analysisSituation().then((res) => {
      // 确保DOM和Cesium加载完成
      if (res.code == 200) {
        this.$nextTick(() => {
          if (window.Cesium) {
            this.initCesiumData = res;
            this.initCesiumContainer();
            this.createAreaCesium();
          } else {
            console.error("Cesium未加载！");
          }
        });
      }
    });
  },
  beforeDestroy() {
    this.cleanup();
    if (this.viewer) {
      Cesium.destroyObject(this.viewer);
    }
    // 组件销毁时清理实体
    this.clearSectors();
    // 移除事件监听
    this.removeContextMenuListener();
  },
  methods: {
    // 重置通道数据
    resetReplayChannels() {
      this.channels.forEach((channel) => {
        if (channel.type !== "ionosphere") {
          channel.visible = true;
          this.updateChannelTrackVisibility(channel.id, true);
        }
      });

      // 重置通道配置
      this.initializeChannelConfigs();
    },
    // 清除所有航迹
    clearAllTracks() {
      // 遍历entityMap，删除所有实体
      this.entityMap.forEach((entity, uniqueBatchNo) => {
        this.removeEntity(uniqueBatchNo);
      });
      this.entityMap.clear();

      // 清除通道数据
      Object.keys(this.channelTargets).forEach((channelId) => {
        this.channelTargets[channelId] = [];
      });
    },
    // 打开回放抽屉
    openReplayDrawer() {
      this.replayDrawerVisible = true;
      // 暂停实时WebSocket数据
      if (this.wsService) {
        this.wsService.disconnect();
      }
      // 清除当前地图上的所有航迹实体
      this.clearAllTracks();
    },

    // 关闭回放抽屉
    closeReplayDrawer() {
      this.replayDrawerVisible = false;
      // 清除回放航迹
      this.clearAllTracks();
      // 完全重新初始化WebSocket连接
      this.reinitializeWebSocket();
    },
    // 重新初始化WebSocket
    reinitializeWebSocket() {
      // 完全销毁旧的WebSocket连接
      if (this.wsService) {
        this.wsService.disconnect();
        this.wsService.removeListener("cesium-data");
        this.wsService = null;
      }

      // 创建新的WebSocket连接
      this.initWebSocket();

      // 重置通道状态
      this.resetReplayChannels();
    },
    // 处理回放数据
    handleReplayData(dataPoint, resType) {
      const channelId = this.getChannelIdByResType(resType, dataPoint);
      this.processFlightData([dataPoint], channelId);
      this.processTargetData([dataPoint], channelId);
    },
    // 根据资源类型确定通道ID
    getChannelIdByResType(resType, dataPoint) {
      if (resType === 2004) return 1; // 雷达航迹通道
      if (resType === 2007) {
        // 综合空情或ADS-B通道
        return dataPoint.sourceId === 1 ? 2 : 3;
      }
      return 1; // 默认雷达航迹通道
    },
    // 绘制电离层（支持通道控制）
    drawIonosphereLayers() {
      // 先清除已有电离层
      this.clearIonosphereLayers();

      // 获取电离层通道配置
      const ionosphereChannel = this.channels.find((c) => c.id === 4);
      if (!ionosphereChannel || !ionosphereChannel.visible) return;

      const radarConfig = this.initCesiumData?.data?.radarConfig;
      if (!radarConfig) {
        console.error("Radar config not available");
        return;
      }

      const centerLonLat = [radarConfig.latitude, radarConfig.longitude];

      this.ionosphereData.forEach((sectorData) => {
        const innerRadius = sectorData.startRadius * 1000;
        const outerRadius = sectorData.endRadius * 1000;
        const startAngle = sectorData.startAngle;
        const endAngle = sectorData.endAngle;

        // 创建扇环实体
        const sectorEntities = addSectorGridSmall(
          this.viewer,
          centerLonLat,
          innerRadius,
          outerRadius,
          startAngle,
          endAngle
        );

        // 添加频率标签
        const labelEntity = this.addFrequencyLabel(
          centerLonLat,
          sectorData,
          innerRadius,
          outerRadius,
          startAngle,
          endAngle,
          ionosphereChannel.showFrequency
        );

        // 存储实体
        this.ionosphereEntities.push(...sectorEntities, labelEntity);
      });
    },

    // 计算扇区中心坐标
    calculateSectorCenter(centerLonLat, angle, radius) {
      // 添加参数检查
      if (!centerLonLat || centerLonLat.length < 2) {
        console.error("Invalid centerLonLat", centerLonLat);
        return null;
      }
      const [lon, lat] = centerLonLat;
      const radAngle = Cesium.Math.toRadians(angle);

      // 使用更精确的球面坐标计算方法
      const earthRadius = 6378137; // 地球半径（米）
      const angularDistance = radius / earthRadius; // 弧度距离

      // 计算新位置（球面坐标）
      const newLat = Math.asin(
        Math.sin(Cesium.Math.toRadians(lat)) * Math.cos(angularDistance) +
          Math.cos(Cesium.Math.toRadians(lat)) *
            Math.sin(angularDistance) *
            Math.cos(radAngle)
      );

      const newLon =
        Cesium.Math.toRadians(lon) +
        Math.atan2(
          Math.sin(radAngle) *
            Math.sin(angularDistance) *
            Math.cos(Cesium.Math.toRadians(lat)),
          Math.cos(angularDistance) -
            Math.sin(Cesium.Math.toRadians(lat)) * Math.sin(newLat)
        );

      return Cesium.Cartesian3.fromDegrees(
        Cesium.Math.toDegrees(newLon),
        Cesium.Math.toDegrees(newLat)
      );
    },
    // 添加频率标签（保留一位小数）
    addFrequencyLabel(
      center,
      sectorData,
      innerRadius,
      outerRadius,
      startAngle,
      endAngle,
      show
    ) {
      // 计算扇区中心位置
      const midRadius = (innerRadius + outerRadius) / 2;
      const midAngle = (startAngle + endAngle) / 2;

      const position = this.calculateLabelPosition(
        center,
        midAngle,
        midRadius,
        innerRadius,
        outerRadius
      );
      if (!position) {
        console.error("Failed to calculate label position");
        return null;
      }
      // 如果不需要显示频率标签，返回空
      if (!show) return null;

      // 格式化频率（保留一位小数）
      const formattedFrequency = Number(sectorData.bestWorkFrequency).toFixed(
        1
      );

      return this.viewer.entities.add({
        position,
        label: {
          text: `F: ${formattedFrequency}MHz`,
          font: "14px sans-serif",
          fillColor: Cesium.Color.RED,
          outlineColor: Cesium.Color.BLACK,
          outlineWidth: 2,
          style: Cesium.LabelStyle.FILL_AND_OUTLINE,
          verticalOrigin: Cesium.VerticalOrigin.CENTER,
          horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
          pixelOffset: new Cesium.Cartesian2(0, 0),
          disableDepthTestDistance: Number.POSITIVE_INFINITY,
        },
      });
    },
    calculateLabelPosition(center, angle, distance, innerRadius, outerRadius) {
      if (!center || center.length < 2) {
        console.error("Invalid center coordinates", center);
        return null;
      }

      const [lon, lat] = center;

      // 计算标签在扇区中的比例位置 (0-1)
      const positionRatio =
        (distance - innerRadius) / (outerRadius - innerRadius);

      // 确保位置在扇区内 (0.3-0.7范围)
      const adjustedRatio = Math.min(Math.max(positionRatio, 0.3), 0.7);

      // 计算实际距离
      const adjustedDistance =
        innerRadius + (outerRadius - innerRadius) * adjustedRatio;

      // 使用球面坐标计算
      const earthRadius = 6378137; // 地球半径（米）
      const angularDistance = adjustedDistance / earthRadius;
      const radAngle = Cesium.Math.toRadians(angle);

      const radLat = Cesium.Math.toRadians(lat);
      const radLon = Cesium.Math.toRadians(lon);

      const newLat = Math.asin(
        Math.sin(radLat) * Math.cos(angularDistance) +
          Math.cos(radLat) * Math.sin(angularDistance) * Math.cos(radAngle)
      );

      const newLon =
        radLon +
        Math.atan2(
          Math.sin(radAngle) * Math.sin(angularDistance) * Math.cos(radLat),
          Math.cos(angularDistance) - Math.sin(radLat) * Math.sin(newLat)
        );

      return Cesium.Cartesian3.fromRadians(newLon, newLat);
    },
    // 清除电离层
    clearIonosphereLayers() {
      this.ionosphereEntities.forEach((entity) => {
        this.viewer.entities.remove(entity);
      });
      this.ionosphereEntities = [];
    },

    //样式配置
    startDragStyleConfig(event) {
      if (
        event.target.closest(".el-input-number") ||
        event.target.closest(".el-color-picker")
      )
        return;

      this.isDraggingStyleConfig = true;
      this.dragStyleConfigStartPos = {
        x: event.clientX,
        y: event.clientY,
      };
      this.styleConfigDialogStartPos = {
        x: parseInt(this.styleConfigDialogStyle.left),
        y: parseInt(this.styleConfigDialogStyle.top),
      };
    },

    doDragStyleConfig(event) {
      if (!this.isDraggingStyleConfig) return;

      const deltaX = event.clientX - this.dragStyleConfigStartPos.x;
      const deltaY = event.clientY - this.dragStyleConfigStartPos.y;

      const newX = this.styleConfigDialogStartPos.x + deltaX;
      const newY = this.styleConfigDialogStartPos.y + deltaY;

      const maxX = window.innerWidth - 500;
      const maxY = window.innerHeight - 300;

      this.styleConfigDialogStyle = {
        left: `${Math.min(Math.max(newX, 0), maxX)}px`,
        top: `${Math.min(Math.max(newY, 0), maxY)}px`,
        transform: "none",
      };
    },

    stopDragStyleConfig() {
      this.isDraggingStyleConfig = false;
    },

    // 初始化通道配置
    initializeChannelConfigs() {
      this.channels.forEach((channel) => {
        const savedConfig = localStorage.getItem(`channelConfig_${channel.id}`);

        // 确保筛选配置有默认值
        const defaultConfig = {
          ...JSON.parse(JSON.stringify(defaultChannelConfig)),
          filterConfig: {
            targetTypes: [],
            keyAttributes: [],
            reportingAttributes: [],
            reservedAttributes: [],
            allegiance: [],
          },
          styleConfig: {
            fontSize: 14,
            fontColor: "#FFFFFF",
            backgroundColor: "rgba(0,0,0,0.5)",
          },
        };

        this.$set(
          this.channelConfigs,
          channel.id,
          savedConfig ? JSON.parse(savedConfig) : defaultConfig
        );
      });
    },

    // 获取通道目标数据
    getChannelTargets(channelId) {
      return this.channelTargets[channelId] || [];
    },

    // 添加右键菜单事件监听
    addContextMenuListener() {
      const container = document.getElementById("cesiumContainer");
      if (container) {
        container.addEventListener("contextmenu", this.showContextMenu);
      }
    },

    // 移除事件监听
    removeContextMenuListener() {
      const container = document.getElementById("cesiumContainer");
      if (container) {
        container.removeEventListener("contextmenu", this.showContextMenu);
      }
    },

    // 显示右键菜单
    showContextMenu(event) {
      event.preventDefault();

      // 设置菜单位置
      this.contextMenuStyle = {
        top: `${event.clientY}px`,
        left: `${event.clientX}px`,
      };

      // 显示菜单
      this.contextMenuVisible = true;
    },

    // 关闭右键菜单
    closeContextMenu() {
      this.contextMenuVisible = false;
    },

    // 打开通道操作菜单
    openChannelMenu(channel) {
      this.currentChannel = channel;

      // 设置菜单位置（在通道项右侧）
      this.channelMenuStyle = {
        top: this.contextMenuStyle.top,
        left: `${parseInt(this.contextMenuStyle.left) + 320}px`,
      };

      this.channelMenuVisible = true;
    },

    // 切换通道显示
    toggleChannel(channelId) {
      const channel = this.channels.find((c) => c.id === channelId);
      if (channel) {
        channel.visible = !channel.visible;
        // 如果是电离层通道，需要重新绘制
        if (channel.type === "ionosphere") {
          this.drawIonosphereLayers();
        } else {
          this.updateChannelTrackVisibility(channelId, channel.visible);
        }
      }
    },

    // 显示所有目标
    showAllTargets() {
      this.channels
        .filter((c) => c.type !== "ionosphere")
        .forEach((c) => {
          c.visible = true;
          this.updateChannelTrackVisibility(c.id, true);
        });
    },

    // 隐藏所有目标
    hideAllTargets() {
      this.channels
        .filter((c) => c.type !== "ionosphere")
        .forEach((c) => {
          c.visible = false;
          this.updateChannelTrackVisibility(c.id, false);
        });
    },

    // 打开颜色配置
    openColorConfig(channelId) {
      this.currentConfigChannelId = channelId;
      this.colorConfig = { ...this.channelConfigs[channelId].colorConfig };
      this.colorConfigVisible = true;
    },
    // 打开筛选配置
    openFilterConfig(channelId) {
      this.currentConfigChannelId = channelId;
      this.filters = { ...this.channelConfigs[channelId].filterConfig };
      this.filterDialogVisible = true;
    },

    // 打开属性项配置
    openAttributeConfig(channelId) {
      this.currentConfigChannelId = channelId;
      const config = this.channelConfigs[channelId].attributeConfig;

      // 使用当前通道的配置
      this.currentLabelProperties = [...config.labelProperties];
      this.currentTableProperties = [...config.tableProperties];

      this.showTransferDialog = true;
    },

    // 打开样式配置
    openStyleConfig(channelId) {
      this.currentConfigChannelId = channelId;

      // 确保加载正确的配置
      const config = this.channelConfigs[channelId]?.styleConfig;

      if (config) {
        this.currentStyleConfig = { ...config };
      } else {
        console.warn(`通道 ${channelId} 的样式配置未找到，使用默认值`);
        this.currentStyleConfig = { ...defaultChannelConfig.styleConfig };
      }

      this.styleConfigVisible = true;
    },

    // 应用样式配置
    applyStyleConfig() {
      if (this.currentConfigChannelId) {
        this.channelConfigs[this.currentConfigChannelId].styleConfig = {
          ...this.currentStyleConfig,
        };
        this.saveChannelConfig(this.currentConfigChannelId);
        this.updateChannelLabelStyles(this.currentConfigChannelId); // 确保调用更新
        // 强制Cesium重新渲染
        this.viewer.scene.requestRender();
      }
      this.styleConfigVisible = false;
    },

    // 更新通道标牌样式
    updateChannelLabelStyles(channelId) {
      console.log(`更新通道 ${channelId} 的标签样式`);

      this.entityMap.forEach((entity, uniqueBatchNo) => {
        // 确保访问正确的 channelId 属性
        if (entity.channelId === channelId) {
          const style = this.channelConfigs[channelId]?.styleConfig;

          if (!style) {
            console.warn(`通道 ${channelId} 的样式配置未找到`);
            return;
          }

          // 确保实体和标签存在
          if (entity.plane && entity.plane.label) {
            console.log(`更新实体 ${uniqueBatchNo} 的标签样式`, style);

            // 更新字体大小
            entity.plane.label.font = `${style.fontSize}px sans-serif`;

            // 更新字体颜色
            if (style.fontColor) {
              entity.plane.label.fillColor = Cesium.Color.fromCssColorString(
                style.fontColor
              );
            }

            // 更新背景颜色
            if (style.backgroundColor) {
              entity.plane.label.backgroundColor =
                Cesium.Color.fromCssColorString(style.backgroundColor);
            }

            // 强制更新实体
            entity.plane.label = entity.plane.label;
          } else {
            console.warn(`实体 ${uniqueBatchNo} 的标签未找到`, entity);
          }
        }
      });

      // 强制场景重新渲染
      this.viewer.scene.requestRender();
    },

    // 保存通道配置
    saveChannelConfig(channelId) {
      // 如果是电离层通道，需要重新绘制
      if (this.channelConfigs[channelId].type === "ionosphere") {
        this.drawIonosphereLayers();
      }
      localStorage.setItem(
        `channelConfig_${channelId}`,
        JSON.stringify(this.channelConfigs[channelId])
      );
      this.$message.success(`通道 ${channelId} 配置已保存`);
    },

    // 切换通道可见性
    toggleChannelVisibility(channelId) {
      const channel = this.channels.find((c) => c.id === channelId);
      if (channel) {
        channel.visible = !channel.visible;
        this.updateChannelTrackVisibility(channelId, channel.visible);
        this.$message.info(
          `通道 ${channel.name} ${channel.visible ? "已显示" : "已隐藏"}`
        );
      }
    },

    // 更新通道航迹可见性
    updateChannelTrackVisibility(channelId, visible) {
      this.entityMap.forEach((entity, uniqueBatchNo) => {
        if (entity.channelId === channelId) {
          entity.polyline.show = visible;
          entity.plane.show = visible;
        }
      });
    },

    changeColorItemHandle(label, key) {
      console.log("label, key", label, key);
    },
    // 关闭颜色配置弹窗
    closeColorConfig() {
      this.colorConfigVisible = false;
    },
    // 开始拖拽颜色配置弹窗
    startDragColorConfig(event) {
      if (
        event.target.closest(".el-color-picker") ||
        event.target.closest("button")
      )
        return;

      this.isDraggingColorConfig = true;
      this.dragColorConfigStartPos = {
        x: event.clientX,
        y: event.clientY,
      }; //记录鼠标位置
      this.colorConfigDialogStartPos = {
        x: parseInt(this.colorConfigDialogStyle.left),
        y: parseInt(this.colorConfigDialogStyle.top),
      }; //记录弹窗初始化位置
    },

    // 拖拽颜色配置弹窗
    doDragColorConfig(event) {
      if (!this.isDraggingColorConfig) return;

      const deltaX = event.clientX - this.dragColorConfigStartPos.x;
      const deltaY = event.clientY - this.dragColorConfigStartPos.y;
      // 鼠标移动的距离

      const newX = this.colorConfigDialogStartPos.x + deltaX;
      const newY = this.colorConfigDialogStartPos.y + deltaY;
      //弹窗跟随鼠标移动的位置

      // 限制在可视范围内
      const maxX = window.innerWidth - 800; // 弹窗宽度800px
      const maxY = window.innerHeight - 600; // 弹窗高度约600px

      this.colorConfigDialogStyle = {
        left: `${Math.min(Math.max(newX, 0), maxX)}px`,
        top: `${Math.min(Math.max(newY, 0), maxY)}px`,
        transform: "none",
      };
    },
    stopDragColorConfig() {
      this.isDraggingColorConfig = false;
    },
    // 重置颜色配置
    resetColorConfig() {
      this.colorConfig = {
        colorBy: "allegiance",
        allegiance: {
          敌我: "#FF0000",
          我机: "#00FF00",
          友机: "#0000FF",
          中立: "#FFFF00",
          不明: "#AAAAAA",
        },
        reporting: {
          已上报: "#00FF00",
          未上报: "#FF0000",
        },
        keyAttribute: {
          重点目标: "#FF0000",
          非重点目标: "#00FF00",
        },
        targetType: {
          对空: "#FF0000",
          对海: "#0000FF",
          对弹: "#00FF00",
        },
        reserved: {
          保留目标: "#00FF00",
          未保留: "#FF0000",
        },
      };
    },

    // 应用颜色配置
    applyColorConfig() {
      if (this.currentConfigChannelId) {
        this.channelConfigs[this.currentConfigChannelId].colorConfig = {
          ...this.colorConfig,
        };
        this.saveChannelConfig(this.currentConfigChannelId);
        this.updateChannelTrackColors(this.currentConfigChannelId); // 确保调用
      }
      this.colorConfigVisible = false;
    },

    // 在 getEntityColor 方法中添加默认值处理
    getEntityColor(properties, colorConfig) {
      try {
        let colorValue = "#FF0000"; // 默认红色

        switch (colorConfig.colorBy) {
          case "allegiance":
            colorValue =
              colorConfig.allegiance[properties.allegiance] || "#FF0000";
            break;
          case "reporting":
            const reportingKey = properties.reported ? "已上报" : "未上报";
            colorValue = colorConfig.reporting[reportingKey] || "#00FF00";
            break;
          case "keyAttribute":
            colorValue =
              colorConfig.keyAttribute[properties.priority] || "#0000FF";
            break;
          case "targetType":
            colorValue =
              colorConfig.targetType[properties.targetType] || "#FFFF00";
            break;
          case "reserved":
            const reservedKey = properties.retained ? "保留目标" : "未保留";
            colorValue = colorConfig.reserved[reservedKey] || "#FF00FF";
            break;
        }

        return colorValue;
      } catch (e) {
        console.error("获取颜色失败:", e);
        return "#FF0000"; // 出错时返回红色
      }
    },
    // 更新通道航迹颜色
    updateChannelTrackColors(channelId) {
      const colorConfig = this.channelConfigs[channelId].colorConfig;

      this.entityMap.forEach((entity, uniqueBatchNo) => {
        if (entity.channelId === channelId) {
          const properties = entity.properties;
          const colorValue = this.getEntityColor(properties, colorConfig);

          if (colorValue) {
            const cesiumColor = Cesium.Color.fromCssColorString(colorValue);
            entity.polyline.polyline.material = cesiumColor;
          }
        }
      });
    },

    // 从批次号获取通道ID
    getChannelFromBatch(batchNo) {
      // 实际项目中需要根据批次号确定通道
      // 这里简化为取第一个数字作为通道ID
      const match = batchNo.match(/^(\d)/);
      return match ? parseInt(match[1]) : 1;
    },

    //目标筛选
    stopDragFilter() {
      this.isDraggingFilter = false;
      document.removeEventListener("mousemove", this.onDragFilter);
      document.removeEventListener("mouseup", this.stopDragFilter);
    },

    //目标筛选
    starDragFilter(e) {
      if (e.target.closest(".el-dialog__header")) {
        this.isDraggingFilter = true;
        this.dragFilterStartPos = {
          x: e.clientX - this.filterDialogPos.x,
          y: e.clientY - this.filterDialogPos.y,
        };
        document.addEventListener("mousemove", this.onDragFilter);
        document.addEventListener("mouseup", this.stopDragFilter);
      }
    },
    onDragFilter(e) {
      if (!this.isDraggingFilter) return;

      this.filterDialogPos = {
        x: e.clientX - this.dragFilterStartPos.x,
        y: e.clientY - this.dragFilterStartPos.y,
      };
      const maxX = window.innerWidth - 600;
      const maxY = window.innerHeight - 400;
      this.filterDialogPos.x = Math.min(
        Math.max(this.filterDialogPos.x, 20),
        maxX
      );
      this.filterDialogPos.y = Math.min(
        Math.max(this.filterDialogPos.y, 20),
        maxY
      );
      //更新弹窗位置
      this.dialogStyle = {
        left: `${this.filterDialogPos.x}px`,
        top: `${this.filterDialogPos.y}px`,
        transform: "none",
      };
    },
    calculateTableWidth() {
      let totalWidth = 0;
      this.tableColumns.forEach((col) => {
        if (col.width && col.width.endsWith("px")) {
          totalWidth += parseInt(col.width);
        } else {
          totalWidth += 120;
        }
        this.tableColumns = `${totalWidth}px`;
      });
    },

    // 同步表头滚动
    syncHeaderScroll() {
      if (this.$refs.headerContainer && this.$refs.bodyContainer) {
        this.$refs.headerContainer.scrollLeft =
          this.$refs.bodyContainer.scrollLeft;
      }
    },

    // 从WebSocket数据中提取动态属性
    extractDynamicProperties(dataList) {
      if (!dataList || dataList.length === 0) return;

      // 收集所有唯一属性键
      const allKeys = new Set();
      dataList.forEach((item) => {
        Object.keys(item).forEach((key) => {
          // 排除基础属性
          if (!this.baseProperties.some((prop) => prop.key === key)) {
            allKeys.add(key);
          }
        });
      });

      // 创建动态属性数组
      this.dynamicProperties = Array.from(allKeys).map((key) => {
        // 尝试获取预定义的标签
        const predefinedLabel = this.getPredefinedLabel(key);
        return {
          key,
          label: predefinedLabel || this.formatKeyToLabel(key),
        };
      });
    },

    // 获取预定义的标签（如果有）
    getPredefinedLabel(key) {
      const predefined = {
        DDoppler: "多普勒频移",
        am: "幅度",
        direction: "方向",
        freq: "频率",
        importantFlag: "重点目标",
        pd: "脉宽",
        realBatchNo: "真实批次号",
        receiveTime: "接收时间",
        relationshipFlag: "关系标志",
        reportFlag: "上报标志",
        reserveFlag: "保留标志",
        snr: "信噪比",
        vr: "径向速度",
        heading: "航向",
        timestamp: "更新时间",
      };
      return predefined[key];
    },
    // 格式化键为标签
    formatKeyToLabel(key) {
      // 将驼峰命名转换为空格分隔
      const withSpaces = key.replace(/([A-Z])/g, " $1").trim();
      // 首字母大写
      return withSpaces.charAt(0).toUpperCase() + withSpaces.slice(1);
    },

    // 选择属性
    selectProp(prop) {
      this.selectedProp = prop;
    },
    // 选择标牌属性
    selectLabelProp(prop) {
      this.selectedLabelProp = prop;
      this.selectedProp = null;
      this.selectedTableProp = null;
    },
    // 选择表格属性
    selectTableProp(prop) {
      this.selectedTableProp = prop;
      this.selectedProp = null;
      this.selectedLabelProp = null;
    },
    // 添加到标牌属性
    addToLabels() {
      if (
        this.selectedProp &&
        !this.labelProperties.includes(this.selectedProp)
      ) {
        this.labelProperties.push(this.selectedProp);
        this.selectedProp = null;
      }
    },

    // 从标牌属性移除
    removeFromLabels() {
      if (this.selectedLabelProp) {
        this.labelProperties = this.labelProperties.filter(
          (p) => p !== this.selectedLabelProp
        );
        this.selectedLabelProp = null;
      }
    },

    addToTables() {
      if (
        this.selectedProp &&
        !this.tableProperties.includes(this.selectedProp)
      ) {
        this.tableProperties.push(this.selectedProp);
        this.selectedProp = null;
      }
    },

    // 从表格属性移除
    removeFromTables() {
      if (this.selectedTableProp) {
        this.tableProperties = this.tableProperties.filter(
          (p) => p !== this.selectedTableProp
        );
        this.selectedTableProp = null;
      }
    },

    // 保存属性配置
    saveConfig() {
      if (this.currentConfigChannelId) {
        this.channelConfigs[this.currentConfigChannelId].attributeConfig = {
          labelProperties: [...this.currentLabelProperties],
          tableProperties: [...this.currentTableProperties],
        };
        this.saveChannelConfig(this.currentConfigChannelId);
      }
      this.showTransferDialog = false;
    },

    // 恢复默认配置
    resetConfig() {
      this.labelProperties = ["batchNo", "longitude", "latitude"];
      this.tableProperties = [
        "batchNo",
        "longitude",
        "latitude",
        "altitude",
        "speed",
        "targetType",
      ];
      this.$message.success("已恢复默认配置");
    },

    // 生成表格列
    generateTableColumns() {
      this.tableColumns = this.tableProperties.map((prop) => {
        const property = this.allProperties.find((p) => p.key === prop);
        return {
          key: prop,
          label: property ? property.label : prop,
          width: this.getColumnWidth(prop),
        };
      });
    },

    // 根据属性类型设置列宽
    getColumnWidth(prop) {
      switch (prop) {
        case "batchNo":
          return "120px";
        case "longitude":
        case "latitude":
          return "140px";
        case "altitude":
        case "speed":
          return "100px";
        case "timestamp":
          return "180px";
        default:
          return "150px"; //所有列固定宽度
      }
    },
    // 获取属性标签
    getPropertyLabel(prop) {
      const property = this.allProperties.find((p) => p.key === prop);
      return property ? property.label : this.formatKeyToLabel(prop);
    },
    // 获取属性值
    getPropertyValue(entity, prop) {
      const value = entity[prop];

      // 特殊处理空值
      if (value === null || value === undefined) {
        return "N/A";
      }

      // 特殊处理常见属性
      switch (prop) {
        case "batchNo":
        case "realBatchNo":
          return value;
        case "longitude":
          return value.toFixed(6);
        case "latitude":
          return value.toFixed(6);
        case "altitude":
          return `${value} 米`;
        case "speed":
          return `${value} 节`;
        case "targetType":
          return this.mapTargetChannel(entity.targetChannel);
        case "snr":
          return value ? value.toFixed(2) : "N/A";
        case "allegiance":
          return this.mapRelationship(entity.relationshipFlag);
        case "sourceId":
          return `Source ${value}`;
        case "heading":
          return value ? `${value.toFixed(1)}°` : "N/A";
        case "timestamp":
          return entity.timestamp
            ? new Date(entity.timestamp).toLocaleString()
            : "N/A";
        case "receiveTime":
          return value;
        case "importantFlag":
          return value ? "是" : "否";
        case "reportFlag":
        case "reserveFlag":
          return value === 1 ? "是" : "否";
        case "DDoppler":
        case "am":
        case "direction":
        case "freq":
        case "pd":
        case "vr":
          return typeof value === "number" ? value.toFixed(2) : value;
        default:
          // 通用处理
          if (typeof value === "number") {
            return value.toFixed(2);
          }
          return value.toString();
      }
    },

    // 从本地存储加载配置
    loadConfigFromLocalStorage() {
      const savedLabelProps = localStorage.getItem("labelProperties");
      const savedTableProps = localStorage.getItem("tableProperties");

      if (savedLabelProps) {
        this.labelProperties = JSON.parse(savedLabelProps);
      } else {
        // 设置默认值
        this.labelProperties = ["batchNo", "longitude", "latitude"];
      }

      if (savedTableProps) {
        this.tableProperties = JSON.parse(savedTableProps);
      } else {
        // 设置默认值
        this.tableProperties = [
          "batchNo",
          "longitude",
          "latitude",
          "altitude",
          "speed",
          "targetType",
        ];
      }

      this.generateTableColumns();
    },

    // 处理穿梭框变化
    handleTransferChange(value, direction, movedKeys) {
      if (direction === "left") {
        this.transferData.left = value;
      } else {
        this.transferData.right = value;
      }
    },

    // 格式化单元格值
    formatCellValue(item, key) {
      const value = item[key];
      switch (key) {
        case "longitude":
        case "latitude":
          return value.toFixed(2);
        case "altitude":
          return `${value} m`;
        case "speed":
          return `${value} 节`;
        case "timestamp":
          return this.formatDateTime(value);
        default:
          return value;
      }
    },

    // 格式化时间
    formatDateTime(timestamp) {
      return new Date(timestamp).toLocaleTimeString();
    },
    // 处理下拉菜单命令
    handleCommand(command) {
      if (command === "c") {
        this.showTransferDialog = true;
      } else if (command === "b") {
        this.filterDialogVisible = true;
      } else if (command === "a") {
        this.openColorConfig();
      } else {
        this.$message(`点击了选项 ${command}`);
      }
    },
    // 新增目标监控弹窗方法
    toggleTargetWindow() {
      this.showTargetWindow = !this.showTargetWindow;
      if (this.showTargetWindow) {
        this.targetWindowPos = {
          x: window.innerWidth - 1600,
          y: 100,
        };
      }
    },

    startDragTargetWindow(e) {
      if (e.target.closest(".window-header")) {
        this.isDraggingTargetWindow = true;
        this.dragTargetStartPos = {
          x: e.clientX - this.targetWindowPos.x,
          y: e.clientY - this.targetWindowPos.y,
        };
        document.addEventListener("mousemove", this.onDragTargetWindow);
        document.addEventListener("mouseup", this.stopDragTargetWindow);
      }
    },

    onDragTargetWindow(e) {
      if (!this.isDraggingTargetWindow) return;

      this.targetWindowPos = {
        x: e.clientX - this.dragTargetStartPos.x,
        y: e.clientY - this.dragTargetStartPos.y,
      };

      // 边界限制
      const maxX = window.innerWidth - 800;
      const maxY = window.innerHeight - 500;

      this.targetWindowPos.x = Math.min(
        Math.max(this.targetWindowPos.x, 20),
        maxX
      );
      this.targetWindowPos.y = Math.min(
        Math.max(this.targetWindowPos.y, 20),
        maxY
      );
    },

    stopDragTargetWindow() {
      this.isDraggingTargetWindow = false;
      document.removeEventListener("mousemove", this.onDragTargetWindow);
      document.removeEventListener("mouseup", this.stopDragTargetWindow);
    },

    // 处理滚动
    handleTabScroll() {
      if (this.$refs.bodyContainer) {
        this.scrollTop = this.$refs.bodyContainer.scrollTop;
        this.syncHeaderScroll();
      }
    },

    // 处理目标监控数据（新增channelId参数）
    processTargetData(dataList, channelId) {
      dataList.forEach((item) => {
        if (item.missFlag) {
          this.removeTarget(item.uniqueBatchNo);
          return;
        }

        // 更新或添加目标到对应通道
        this.updateOrAddTarget(channelId, item);
      });

      // 提取动态属性
      this.extractDynamicProperties(dataList);
    },

    updateDisplay(data) {
      this.clearEntities();
      data.forEach((item) => {
        this.entities.push(this.createSector(item));
      });
    },

    // 清除所有实体
    clearEntities() {
      this.entities.forEach((e) => {
        this.viewer.entities.remove(e.sector);
        this.viewer.entities.remove(e.label);
      });
      this.entities = [];
    },
    // 更新或添加目标到指定通道
    updateOrAddTarget(channelId, newItem) {
      if (!this.channelTargets[channelId]) {
        this.$set(this.channelTargets, channelId, []);
      }

      const targetList = this.channelTargets[channelId];
      const index = targetList.findIndex(
        (t) => t.uniqueBatchNo === newItem.uniqueBatchNo
      );

      if (index !== -1) {
        // 更新现有目标
        this.$set(targetList, index, {
          ...targetList[index],
          ...newItem,
          timestamp: Date.now(),
        });
      } else {
        // 添加新目标
        this.$set(targetList, targetList.length, {
          ...newItem,
          timestamp: Date.now(),
        });
      }

      // 按时间倒序排序
      targetList.sort((a, b) => b.timestamp - a.timestamp);
    },

    // 移除目标
    removeTarget(uniqueBatchNo) {
      // 从所有目标数组中移除
      Object.keys(this.channelTargets).forEach((channelId) => {
        const targetList = this.channelTargets[channelId];
        const index = targetList.findIndex(
          (t) => t.uniqueBatchNo === uniqueBatchNo
        );
        if (index !== -1) {
          targetList.splice(index, 1);
        }
      });

      // 如果移除的是当前选中的目标，取消选中
      if (this.selectedTarget === uniqueBatchNo) {
        this.selectedTarget = null;
      }
    },

    // 选择目标
    selectTarget(target) {
      this.selectedTarget = target.uniqueBatchNo;

      // 在地图上高亮选中的目标
      const entity = this.entityMap.get(target.uniqueBatchNo);
      if (entity) {
        this.handleBatchClick(target.uniqueBatchNo, entity);
      }
    },
    // 绘制多个扇环网格的方法
    drawSectors(sectorDataList) {
      // 清除之前的扇区实体
      this.clearSectors();
      // 获取雷达中心点配置
      const radarConfig = this.initCesiumData?.data?.radarConfig;
      if (!radarConfig) return;

      const centerLonLat = [radarConfig.latitude, radarConfig.longitude]; // [经度, 纬度]

      // 遍历扇环数据并创建实体
      sectorDataList.forEach((sectorData) => {
        const innerRadius = sectorData.startRadius * 1000; // 千米转米
        const outerRadius = sectorData.endRadius * 1000; // 千米转米
        const startAngle = sectorData.startAngle;
        const endAngle = sectorData.endAngle;
        const entities = addSectorGridSmall(
          this.viewer,
          centerLonLat,
          innerRadius,
          outerRadius,
          startAngle,
          endAngle
        );
        // 存储新创建的实体
        this.sectorEntities.push(...entities);
      });
    },
    // 清除所有扇区实体的方法
    clearSectors() {
      this.sectorEntities.forEach((entity) => {
        this.viewer.entities.remove(entity);
      });
      this.sectorEntities = []; // 清空数组
    },
    mapTargetChannel(val) {
      const map = { 1: "对空", 2: "对海", 3: "对弹" };
      return map[val] || "未知类型";
    },

    // 虚拟列表行样式
    getRowStyle(item, index) {
      const rowIndex = this.startIndex + index;
      return {
        position: "absolute",
        top: `${rowIndex * ROW_HEIGHT}px`,
        width: "100%",
        height: `${ROW_HEIGHT}px`,
        left: 0,
      };
    },

    mapRelationship(val) {
      const map = { 0: "不明", 1: "敌我", 2: "我机", 3: "友机", 4: "中立" };
      return map[val] || "不明";
    },
    normalizeFlightData(item) {
      return {
        ...item,
        targetType: this.mapTargetChannel(item.targetChannel), //接受数据全是对空1
        priority: item.importantFlag ? "重点目标" : "非重点目标", //重点属性暂时未解析
        allegiance: this.mapRelationship(item.relationshipFlag), //敌我属性暂时未解析
        retained: item.reserveFlag === 1, //保留属性暂时未解析
        reported: item.reportFlag === 1, //上报目标0是未上报，1是上报
      };
    },
    // 重置筛选
    resetFilters() {
      this.filters = {
        targetTypes: [],
        keyAttributes: [],
        reportingAttributes: [],
        reservedAttributes: [],
        allegiance: [],
      };
      this.applyFilters();
    },

    // 筛选配置应用
    applyFilters() {
      if (this.currentConfigChannelId) {
        // 确保正确保存筛选配置
        this.channelConfigs[this.currentConfigChannelId].filterConfig = {
          ...this.filters,
        };

        // 保存到本地存储
        this.saveChannelConfig(this.currentConfigChannelId);

        // 立即应用筛选
        this.updateChannelTrackFilter(this.currentConfigChannelId);
      }
      this.filterDialogVisible = false;
    },

    // 更新通道航迹筛选
    updateChannelTrackFilter(channelId) {
      const filterConfig = this.channelConfigs[channelId]?.filterConfig;
      if (!filterConfig) return;

      // 遍历所有实体，只处理当前通道的实体
      this.entityMap.forEach((entity, uniqueBatchNo) => {
        if (entity.channelId === channelId) {
          this.applyFilterToEntity(uniqueBatchNo, channelId);
        }
      });
    },

    // 检查实体可见性
    checkEntityVisibility(properties, filterConfig) {
      // 目标类型筛选
      if (filterConfig.targetTypes.length > 0) {
        const targetTypeMatch = filterConfig.targetTypes.includes(
          properties.targetType
        );
        if (!targetTypeMatch) return false;
      }

      // 重点属性筛选
      if (filterConfig.keyAttributes.length > 0) {
        const isKeyTarget = properties.priority === "重点目标";
        const shouldShowKey =
          filterConfig.keyAttributes.includes("重点目标") && isKeyTarget;
        const shouldShowNonKey =
          filterConfig.keyAttributes.includes("非重点目标") && !isKeyTarget;

        if (!shouldShowKey && !shouldShowNonKey) return false;
      }

      // 上报属性筛选
      if (filterConfig.reportingAttributes.length > 0) {
        const isReported = properties.reported;
        const shouldShowReported =
          filterConfig.reportingAttributes.includes("已上报") && isReported;
        const shouldShowUnreported =
          filterConfig.reportingAttributes.includes("未上报") && !isReported;

        if (!shouldShowReported && !shouldShowUnreported) return false;
      }

      // 保留属性筛选
      if (filterConfig.reservedAttributes.length > 0) {
        const isReserved = properties.retained;
        const shouldShowReserved =
          filterConfig.reservedAttributes.includes("保留目标") && isReserved;
        const shouldShowUnreserved =
          filterConfig.reservedAttributes.includes("未保留") && !isReserved;

        if (!shouldShowReserved && !shouldShowUnreserved) return false;
      }

      // 敌我属性筛选
      if (filterConfig.allegiance.length > 0) {
        const allegianceMatch = filterConfig.allegiance.includes(
          properties.allegiance
        );
        if (!allegianceMatch) return false;
      }

      return true;
    },

    //航迹高亮
    handleBatchClick(uniqueBatchNo, entityData) {
      // 防抖处理
      if (this.debounceTimeout) return;
      this.debounceTimeout = setTimeout(() => {
        this.debounceTimeout = null;
      }, 300);

      // 获取目标数据
      const target = this.currentTabData.find(
        (t) => t.uniqueBatchNo === uniqueBatchNo
      );
      if (!target) return;

      // 点击已选中的批次时取消选择
      if (this.selectedBatch?.uniqueBatchNo === uniqueBatchNo) {
        this.restoreBatchAppearance();
        this.infoWindowVisible = false;
        return;
      }
      // 设置当前选中批次
      this.selectedBatch = {
        uniqueBatchNo,
        ...target,
        sourceId: this.getSourceIdFromBatchNo(uniqueBatchNo),
      };

      this.infoWindowVisible = true;
    },
    restoreBatchAppearance() {
      if (this.highlightTrail && this.originalPositions.length > 0) {
        this.highlightTrail.polyline.positions = this.originalPositions;
      }
      if (!this.selectedBatch) return;

      const entity = this.entityMap.get(this.selectedBatch.uniqueBatchNo);
      if (!entity) return;

      // 恢复原始材质和宽度
      entity.polyline.polyline.material = this.selectedBatch.originalMaterial;
      entity.polyline.polyline.width = new Cesium.ConstantProperty(
        this.selectedBatch.originalWidth
      );

      this.selectedBatch = null;
      this.infoWindowVisible = false;
    },
    closeInfoWindow() {
      this.restoreBatchAppearance();
      this.infoWindowVisible = false;
    },

    // 辅助方法：从 uniqueBatchNo 解析 sourceId
    getSourceIdFromBatchNo(uniqueBatchNo) {
      return parseInt(uniqueBatchNo.split("_")[1]);
    },

    // 处理航迹数据（新增channelId参数）
    processFlightData(dataList, channelId) {
      dataList.forEach((item) => {
        // 添加通道ID标识
        const itemWithChannel = { ...item, channelId };

        if (item.missFlag) {
          this.removeEntity(item.uniqueBatchNo);
          return;
        }

        // 创建/更新航迹
        this.updateOrCreateEntity(itemWithChannel);
      });
    },

    // 创建或更新航迹实体
    updateOrCreateEntity(item) {
      const {
        sourceId,
        latitude,
        longitude,
        uniqueBatchNo,
        batchNo,
        channelId,
      } = item;
      const waypoint = {
        ...item,
        longitude,
        latitude,
        uniqueBatchNo,
        batchNo,
        channelId,
      };

      if (!this.entityMap.has(uniqueBatchNo)) {
        this.createNewTrack(uniqueBatchNo, sourceId, waypoint);
      } else {
        this.updateExistingTrack(uniqueBatchNo, waypoint);
      }
      // 添加实体后强制渲染
      if (this.viewer) {
        this.viewer.scene.requestRender();
      }
    },

    createNewTrack(uniqueBatchNo, sourceId, initialWaypoint) {
      const channelId = initialWaypoint.channelId;

      const polyline = this.viewer.entities.add({
        polyline: {
          positions: [],
          width: 2,
          material: Cesium.Color.RED, // 默认红色, //TODO
        },
      });

      const plane = this.viewer.entities.add({
        billboard: {
          image: require("@/assets/images/airplane.svg"),
          width: 25,
          height: 25,
          zIndex: 20, // 设置最高的 zIndex
          disableDepthTestDistance: Number.POSITIVE_INFINITY,
          rotation: new Cesium.CallbackProperty(
            () => this.calculatePlaneRotation(plane),
            false
          ),
        },
        label: {
          text: String(initialWaypoint.batchNo),
          font: "14px sans-serif",
          fillColor: Cesium.Color.WHITE,
          outlineColor: Cesium.Color.BLACK,
          outlineWidth: 2,
          verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
          pixelOffset: new Cesium.Cartesian2(0, -20),
        },
      });

      this.entityMap.set(uniqueBatchNo, {
        polyline,
        plane,
        channelId, // 存储通道ID
        positions: [
          Cesium.Cartesian3.fromDegrees(
            initialWaypoint.longitude,
            initialWaypoint.latitude
          ),
        ],
        properties: {
          targetType: this.mapTargetChannel(initialWaypoint.targetChannel),
          priority: initialWaypoint.importantFlag ? "重点目标" : "非重点目标",
          allegiance: this.mapRelationship(initialWaypoint.relationshipFlag),
          retained: initialWaypoint.reserveFlag === 1,
          reported: initialWaypoint.reportFlag === 1,
        },
        initialStyle: {
          font: "14px sans-serif",
          fillColor: Cesium.Color.WHITE,
          backgroundColor: Cesium.Color.BLACK.withAlpha(0.5),
        },
      });
      // 创建后立即应用筛选配置
      this.applyFilterToEntity(uniqueBatchNo, initialWaypoint.channelId);

      this.startPlaneAnimation(uniqueBatchNo);
    },
    // 应用筛选到单个实体
    applyFilterToEntity(uniqueBatchNo, channelId) {
      const entity = this.entityMap.get(uniqueBatchNo);
      if (!entity) return;

      const filterConfig = this.channelConfigs[channelId]?.filterConfig;
      if (!filterConfig) return;

      const visible = this.checkEntityVisibility(
        entity.properties,
        filterConfig
      );

      entity.polyline.show = visible;
      entity.plane.show = visible;
    },
    //更新已有航迹
    updateExistingTrack(uniqueBatchNo, waypoint) {
      const entity = this.entityMap.get(uniqueBatchNo);
      const newPosition = Cesium.Cartesian3.fromDegrees(
        waypoint.longitude,
        waypoint.latitude
      );

      // 更新航迹路径
      entity.positions.push(newPosition);
      entity.polyline.polyline.positions = entity.positions;

      // 直接设置飞机位置到最新点
      entity.plane.position = newPosition;

      // 更新批号标签
      entity.plane.label.text = waypoint.batchNo
        ? String(waypoint.batchNo)
        : ""; // 更新标签内容

      // 更新实体属性
      entity.properties = {
        targetType: this.mapTargetChannel(waypoint.targetChannel),
        priority: waypoint.importantFlag ? "重点目标" : "非重点目标",
        allegiance: this.mapRelationship(waypoint.relationshipFlag),
        retained: waypoint.reserveFlag === 1,
        reported: waypoint.reportFlag === 1,
      };

      // 更新后重新应用筛选
      this.applyFilterToEntity(uniqueBatchNo, waypoint.channelId);
    },
    // 启动飞机动画
    startPlaneAnimation(uniqueBatchNo) {
      const entity = this.entityMap.get(uniqueBatchNo);
      if (!entity || entity.positions.length < 2) return;

      // 1. 清除旧位置数据
      entity.plane.position = undefined;

      // 2. 创建时间轴（关键修改点）
      const start = Cesium.JulianDate.fromDate(new Date());
      const stop = Cesium.JulianDate.addSeconds(
        start,
        60,
        new Cesium.JulianDate()
      );

      // 3. 创建插值属性
      const property = new Cesium.SampledPositionProperty();
      entity.positions.forEach((pos, i) => {
        const time = Cesium.JulianDate.addSeconds(
          start,
          (i / (entity.positions.length - 1)) * 60,
          new Cesium.JulianDate()
        );
        property.addSample(time, pos);
      });

      // 4. 绑定到实体
      entity.plane.position = property;

      // 5. 配置时钟（关键修改点）
      this.viewer.clock.startTime = start;
      this.viewer.clock.stopTime = stop;
      this.viewer.clock.currentTime = start;
      this.viewer.clock.clockRange = Cesium.ClockRange.LOOP;
      this.viewer.clock.multiplier = 1;

      // 6. 启动时钟
      this.viewer.clock.shouldAnimate = true;
    },

    // 删除航迹
    removeEntity(uniqueBatchNo) {
      if (!this.entityMap.has(uniqueBatchNo)) return;
      // 如果删除的是当前选中的批次
      if (this.selectedBatch?.uniqueBatchNo === uniqueBatchNo) {
        this.closeInfoWindow();
      }
      const { polyline, plane } = this.entityMap.get(uniqueBatchNo);

      // 销毁实体
      this.viewer.entities.remove(polyline);
      this.viewer.entities.remove(plane);

      // 清理资源
      polyline.positions = [];
      plane.position = undefined;

      this.entityMap.delete(uniqueBatchNo);
    },

    calculatePlaneRotation(planeEntity) {
      try {
        const now = Cesium.JulianDate.now();

        // 检查位置属性是否存在
        if (!planeEntity.position) {
          return this.lastKnownRotation || 0;
        }

        const position = planeEntity.position?.getValue(now);
        if (!position) {
          return this.lastKnownRotation || 0;
        }

        const nextTime = Cesium.JulianDate.addSeconds(
          now,
          0.1,
          new Cesium.JulianDate()
        );

        const nextPos = planeEntity.position?.getValue(nextTime);
        if (!nextPos) {
          return this.lastKnownRotation || 0;
        }

        // 1. 计算方向向量（三维空间）
        const direction = new Cesium.Cartesian3();
        Cesium.Cartesian3.subtract(nextPos, position, direction);

        // 2. 转换为东北天坐标系（ENU）
        const enuMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(position);
        const enuDirection = Cesium.Matrix4.multiplyByPointAsVector(
          Cesium.Matrix4.inverseTransformation(enuMatrix, new Cesium.Matrix4()),
          direction,
          new Cesium.Cartesian3()
        );

        // 3. 计算正北方向夹角（弧度）
        const heading = Math.atan2(enuDirection.x, enuDirection.y);
        this.lastKnownRotation = -heading; // 保存有效值
        // 4. 调整角度匹配朝北SVG（正北为0，顺时针增加）
        return this.lastKnownRotation;
      } catch (error) {
        return this.lastKnownRotation || 0; // 避免未初始化问题;
      }
    },
    createAreaCesium() {
      this.highlighter = new PolarGridHighlighter(
        this.viewer,
        Cesium.Cartesian3.fromDegrees(
          this.initCesiumData?.data?.radarConfig?.latitude,
          this.initCesiumData?.data?.radarConfig?.longitude
        ),
        this.initCesiumData?.data?.powerConfig?.radiusInterval,
        this.initCesiumData?.data?.powerConfig?.angelInterval * 1000
      );
    },
    //初始化cesium
    initCesiumContainer() {
      this.viewer = new Cesium.Viewer("cesiumContainer", {
        baseLayerPicker: false,
        imageryProvider: false,
        sceneMode: Cesium.SceneMode.SCENE2D,
        animation: false,
        geocoder: false,
        homeButton: false,
        sceneModePicker: false,
        navigationHelpButton: false,
        timeline: false,
        infoBox: false,
        fullscreenButton: true,
      });
      // 获取默认的必应底图并移除（如果存在）
      const defaultLayer = this.viewer.imageryLayers.get(0);
      if (defaultLayer) {
        this.viewer.imageryLayers.remove(defaultLayer);
      }

      //瓦片图中心显示
      var centerLongitude = 131;
      var centerLatitude = 40.81;
      var halfSize = 0.05;

      // 创建限定显示范围的矩形区域
      var rectangle = Cesium.Rectangle.fromDegrees(
        centerLongitude - halfSize,
        centerLatitude - halfSize,
        centerLongitude + halfSize,
        centerLatitude + halfSize
      );

      // 禁用用户平移操作
      this.viewer.scene.screenSpaceCameraController.enableTranslate = true;
      // 设置初始视图到矩形中心
      var initialPosition = Cesium.Rectangle.center(rectangle);
      this.viewer.camera.setView({
        destination: Cesium.Cartesian3.fromRadians(
          initialPosition.longitude,
          initialPosition.latitude,
          500000
        ),
        orientation: {
          heading: Cesium.Math.toRadians(0),
          pitch: Cesium.Math.toRadians(-90),
          roll: 0,
        },
      });
      // 可选：进一步限制交互
      this.viewer.scene.screenSpaceCameraController.enableRotate = false;
      this.viewer.scene.screenSpaceCameraController.enableTilt = false;

      // 加载本地瓦片（需提前配置离线数据源）
      const offlineProvider = new Cesium.UrlTemplateImageryProvider({
        url: "/gismap/{z}/{y}/{x}.png",
        minimumLevel: 0,
        maximumLevel: 8,
        tilingScheme: new Cesium.WebMercatorTilingScheme(),
      });
      this.viewer.imageryLayers.addImageryProvider(offlineProvider);

      this.viewer.scene.screenSpaceCameraController.minimumZoomDistance = 10000;
      this.viewer.scene.screenSpaceCameraController.maximumZoomDistance = 10000000;

      // 初始化后动态飞向呼和浩特
      this.viewer.camera.flyTo({
        destination: Cesium.Cartesian3.fromDegrees(131, 40.81, 8000000),
        orientation: {
          heading: Cesium.Math.toRadians(0),
          pitch: Cesium.Math.toRadians(-30),
          roll: 0,
        },
        duration: 2, // 飞行动画时间（秒）
      });

      this.viewer.scene.globe.depthTestAgainstTerrain = true;
      this.viewer.scene.globe.baseColor = Cesium.Color.TRANSPARENT;
      this.viewer.scene.backgroundColor = Cesium.Color.WHITE;

      // 定义扇形参数
      const centerLonLat = [
        this.initCesiumData?.data?.radarConfig?.latitude,
        this.initCesiumData?.data?.radarConfig?.longitude,
      ];
      const innerRadius =
        this.initCesiumData?.data?.radarConfig?.radiusMin * 1000;
      const outerRadius =
        this.initCesiumData?.data?.radarConfig?.radiusMax * 1000;
      const startAngle = this.initCesiumData?.data?.radarConfig?.angleMin;
      const endAngle = this.initCesiumData?.data?.radarConfig?.angelMax;

      // 添加扇环
      this.viewer.entities.add({
        polygon: {
          hierarchy: new Cesium.PolygonHierarchy(
            createAnnularSector(
              centerLonLat,
              innerRadius,
              outerRadius,
              startAngle,
              endAngle
            )
          ),
          material: new Cesium.ColorMaterialProperty(
            Cesium.Color.fromCssColorString("rgba(0, 0, 0, 0.1)")
          ),
          outline: false,
          outlineColor: Cesium.Color.TRANSPARENT,
          height: 0,
        },
      });
      // 添加圆心标记（带实体描述）
      this.viewer.entities.add({
        name: this.initCesiumData?.data?.stationConfigs?.["1"]["name"],
        position: Cesium.Cartesian3.fromDegrees(
          this.initCesiumData?.data?.stationConfigs?.["1"]["latitude"],
          this.initCesiumData?.data?.stationConfigs?.["1"]["longitude"]
        ),
        point: {
          pixelSize: 20,
          color: Cesium.Color.RED,
          outlineColor: Cesium.Color.WHITE,
          outlineWidth: 2,
        },
        label: {
          text: this.initCesiumData?.data?.stationConfigs?.["1"]["name"],
          font: "14px sans-serif",
          fillColor: Cesium.Color.WHITE,
          backgroundColor: Cesium.Color.BLACK.withAlpha(0.5),
          pixelOffset: new Cesium.Cartesian2(0, -30),
          showBackground: true,
          distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
            0,
            1000000000
          ),
        },
      });

      //接收站
      this.viewer.entities.add({
        name: this.initCesiumData?.data?.stationConfigs?.["2"]["name"],
        position: Cesium.Cartesian3.fromDegrees(
          this.initCesiumData?.data?.stationConfigs?.["2"]["latitude"],
          this.initCesiumData?.data?.stationConfigs?.["2"]["longitude"]
        ),
        point: {
          pixelSize: 20,
          color: Cesium.Color.RED,
          outlineColor: Cesium.Color.WHITE,
          outlineWidth: 2,
        },
        label: {
          text: this.initCesiumData?.data?.stationConfigs?.["2"]["name"],
          font: "14px sans-serif",
          fillColor: Cesium.Color.WHITE,
          backgroundColor: Cesium.Color.BLACK.withAlpha(0.5),
          pixelOffset: new Cesium.Cartesian2(0, -30),
          showBackground: true,
          distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
            0,
            1000000000
          ),
        },
      });

      // 调用函数添加网格
      addSectorGrid(
        this.viewer,
        centerLonLat,
        innerRadius,
        outerRadius,
        startAngle,
        endAngle
      );
      // 添加点击事件监听
      const handler = new Cesium.ScreenSpaceEventHandler(
        this.viewer.scene.canvas
      );
      handler.setInputAction((click) => {
        const picked = this.viewer.scene.pick(click.position);
        if (picked && picked.id) {
          const entity = picked.id;
          // 查找对应的批次号
          const batchEntry = Array.from(this.entityMap.entries()).find(
            ([key, value]) =>
              value.polyline === entity || value.plane === entity
          );
          if (batchEntry) {
            const [uniqueBatchNo, entityData] = batchEntry;
            this.handleBatchClick(uniqueBatchNo, entityData);
          }
        }
      }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
    },

    //初始化websocket数据
    initWebSocket() {
      this.wsService = new WebSocketService(
        "ws://172.168.1.222:8899/websocket/5"
      );
      this.wsService.connect();
      this.wsService.addListener("cesium-data", this.handleDataUpdate);
    },
    //接受websocket数据

    handleDataUpdate(dataSource) {
      const { resType, data } = dataSource;
      resTypeCache.set(resType, data);
      this.frequenceData = resTypeCache;
      if (resType == 2002) {
        // 清除上一次的绘制数据
        createHighlightRegions(
          this.viewer,
          [
            this.initCesiumData?.data?.radarConfig?.latitude,
            this.initCesiumData?.data?.radarConfig?.longitude,
          ],
          [data],
          this.initCesiumData?.data?.radarConfig?.angleMin,
          this.initCesiumData?.data?.radarConfig?.radiusMin,
          this.initCesiumData?.data?.powerConfig?.angelInterval,
          this.initCesiumData?.data?.powerConfig?.radiusInterval,
          "#ff0090"
        );
      } else if (resType == 2001) {
        createHighlightRegions(
          this.viewer,
          [
            this.initCesiumData?.data?.radarConfig?.latitude,
            this.initCesiumData?.data?.radarConfig?.longitude,
          ],
          this.frequenceData.get(2001),
          this.initCesiumData?.data?.radarConfig?.angleMin,
          this.initCesiumData?.data?.radarConfig?.radiusMin,
          this.initCesiumData?.data?.powerConfig?.angelInterval,
          this.initCesiumData?.data?.powerConfig?.radiusInterval,
          "#9040ff"
        );
      } else if (resType == 2000) {
        // this.updateDisplay(data);
      } else if (resType == 2006) {
        console.log("电离层数据:", data);

        // 验证扇区数据
        data.forEach((sector, index) => {
          console.log(`扇区 ${index + 1}:`, {
            startRadius: sector.startRadius,
            endRadius: sector.endRadius,
            startAngle: sector.startAngle,
            endAngle: sector.endAngle,
            bestWorkFrequency: sector.bestWorkFrequency,
          });
        });
        //绘制电离层
        // 为每个电离层区域生成唯一ID
        this.ionosphereData = data.map((item, index) => ({
          ...item,
          id: index + 1,
        }));
        this.drawIonosphereLayers();
      } else if (resType == 2004) {
        console.log("12312313", data);

        // 雷达航迹数据 - 全部视为通道1
        this.processFlightData(data, 1);
        this.processTargetData(data, 1);
      } else if (resType == 2007) {
        // 其他航迹数据 - 根据sourceId区分通道
        data.forEach((item) => {
          const channelId = item.sourceId === 1 ? 2 : 3; // sourceId=1->通道2, sourceId=2->通道3
          this.processFlightData([item], channelId);
          this.processTargetData([item], channelId);
        });
      }
      // 添加强制重绘
      this.$nextTick(() => {
        if (this.viewer) {
          this.viewer.scene.requestRender();
          console.log("强制场景重绘"); //TODO切换实时和历史还是有问题
        }
      });
    },
    //清除websocket
    cleanup() {
      this.wsService.removeListener("cesium-data");
      this.wsService.disconnect();
      this.viewer.destroy();
    },
  },
  watch: {
    entityMap: {
      handler(newValue, oldValue) {
        if (newValue.size > 100) {
          const oldestKey = this.entityMap.keys().next().value;
          this.removeEntity(oldestKey);
        }
      },
    },
    currentTabData: {
      handler() {
        // 数据变化时强制更新视图
        this.$nextTick(() => {
          if (this.$refs.scrollContainer) {
            this.$refs.scrollContainer.scrollTop = 0;
          }
        });
      },
      deep: true,
    },
  },
};
</script>

<style lang="less" scoped>
/* 移除冗余样式 */
.cesiumContainerBox {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;

  /* 左上角控制按钮组 */
  .control-buttons {
    position: absolute;
    left: 20px;
    top: 20px;
    z-index: 1000;
    display: flex;
    gap: 15px;

    .ctrl-btn {
      position: relative;
      width: 60px;
      height: 60px;
      border: none;
      border-radius: 15px;
      background: rgba(40, 40, 40, 0.9);
      backdrop-filter: blur(5px);
      cursor: pointer;
      transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
      box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;

      &:hover {
        transform: translateY(-3px);
        box-shadow: 0 6px 12px rgba(0, 0, 0, 0.2);
      }

      &:active {
        transform: translateY(1px);
      }

      .icon {
        font-size: 24px;
        margin-bottom: 2px;
      }

      .label {
        font-size: 12px;
        color: rgba(255, 255, 255, 0.9);
        font-family: "Microsoft YaHei", sans-serif;
        letter-spacing: 0.5px;
      }
    }
  }

  /* 信息弹窗样式 */
  .info-window {
    position: absolute;
    z-index: 1001;
    background: rgba(20, 30, 50, 0.9);
    border-radius: 8px;
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.7);
    border: 1px solid rgba(64, 158, 255, 0.5);
    padding: 15px;
    color: #d0e0f0;
    width: 300px;
    backdrop-filter: blur(5px);

    .info-header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-bottom: 12px;
      border-bottom: 1px solid rgba(64, 158, 255, 0.3);
      padding-bottom: 10px;

      h4 {
        margin: 0;
        color: #409eff;
        font-size: 16px;
      }

      .close-btn {
        background: rgba(100, 30, 30, 0.7);
        border: 1px solid rgba(255, 80, 80, 0.3);
        color: #ffa0a0;
        width: 32px;
        height: 32px;
        border-radius: 50%;
        cursor: pointer;
        display: flex;
        align-items: center;
        justify-content: center;
        transition: all 0.3s;

        &:hover {
          background: rgba(150, 40, 40, 0.8);
          color: white;
        }
      }
    }

    .info-content {
      max-height: 400px;
      overflow-y: auto;

      .info-item {
        margin: 10px 0;
        display: flex;
        justify-content: space-between;

        label {
          color: #a0c0e0;
          font-weight: 500;
          flex: 1;
        }

        span {
          color: #ffffff;
          flex: 1;
          text-align: right;
          font-weight: 500;
        }
      }
    }
  }

  /* 目标监控弹窗样式 */
  .target-monitor-window {
    position: fixed;
    width: 800px;
    height: 500px;
    background: rgba(10, 25, 50, 0.92);
    backdrop-filter: blur(8px);
    border: 1px solid rgba(64, 158, 255, 0.5);
    border-radius: 10px;
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.6);
    display: flex;
    flex-direction: column;
    overflow: hidden;
    z-index: 1003;

    .window-header {
      padding: 12px 20px;
      background: rgba(20, 40, 70, 0.95);
      border-bottom: 1px solid rgba(64, 158, 255, 0.3);
      display: flex;
      justify-content: space-between;
      align-items: center;

      .header-right {
        display: flex;
        align-items: center;
        gap: 15px;
      }

      .tabs {
        display: flex;
        gap: 8px;

        button {
          padding: 8px 15px;
          background: rgba(30, 60, 100, 0.7);
          border: 1px solid rgba(64, 158, 255, 0.3);
          border-radius: 5px;
          color: #a0b9d9;
          font-size: 14px;
          cursor: pointer;
          transition: all 0.3s;

          &:hover {
            background: rgba(40, 80, 130, 0.8);
          }

          &.active {
            background: rgba(64, 158, 255, 0.5);
            color: white;
            border-color: rgba(64, 158, 255, 0.7);
          }
        }
      }

      .close-btn {
        background: none;
        border: none;
        color: #a0b9d9;
        font-size: 18px;
        cursor: pointer;
        padding: 0 5px;

        &:hover {
          color: white;
        }
      }
    }

    .window-content {
      flex: 1;
      overflow: hidden;
      padding: 10px;
      background: rgba(15, 30, 50, 0.85);
      display: flex;
      flex-direction: column;
    }

    /* 虚拟列表容器 */
    .virtual-scroll-container {
      flex: 1;
      display: flex;
      flex-direction: column;
      overflow: hidden;

      .table-header-container {
        flex-shrink: 0;
        overflow: hidden;
        background: rgba(30, 60, 100, 0.9);
        position: relative;
        z-index: 10;
        width: 100%;
        overflow-x: hidden;

        .target-table {
          width: 100%;
          min-width: 100%;
          table-layout: fixed;
          border-collapse: separate;
          border-spacing: 0;

          th {
            padding: 12px 15px;
            color: #a0c0e0;
            font-weight: 600;
            text-align: center;
            border-bottom: 1px solid rgba(64, 158, 255, 0.5);
            white-space: nowrap;
            background-color: rgba(30, 60, 100, 0.9);
          }
        }
      }

      .table-body-container {
        flex: 1;
        overflow: auto;
        width: 100%;

        table {
          width: 100%;
        }

        .virtual-scroll-content {
          position: relative;
          width: 100%;

          .target-table {
            min-width: 100%;
            table-layout: fixed;
            border-collapse: separate;
            border-spacing: 0;

            th,
            td {
              padding: 0 10px;
              overflow: hidden;
              text-overflow: ellipsis;
              white-space: nowrap;
              box-sizing: border-box;
            }

            th {
              position: relative;

              .th-content {
                padding: 12px 5px;
                display: block;
                overflow: hidden;
                text-overflow: ellipsis;
              }
            }

            tbody tr {
              transition: background 0.2s;
              height: 56px;
              line-height: 56px;

              &:hover {
                background: rgba(40, 70, 110, 0.8);
              }

              &.selected {
                background: rgba(64, 158, 255, 0.25);
                color: white;
              }

              td {
                height: 56px;
                line-height: 56px;
                padding: 0 15px;
                text-align: center;
                border-bottom: 1px solid rgba(64, 158, 255, 0.15);
                white-space: nowrap;
                overflow: hidden;
                text-overflow: ellipsis;
                background: rgba(20, 35, 60, 0.7);
                color: white;
              }
            }
          }
        }
      }

      .table-header-container,
      .table-body-container {
        overflow-x: auto;
      }

      .table-header-container table,
      .table-body-container table {
        min-width: 100%;
        table-layout: fixed;
      }
    }
  }
}

/* 全局样式 */
::v-deep .cesium-credit-textContainer,
::v-deep .cesium-credit-logoContainer,
::v-deep .cesium-credit-expand-link {
  display: none !important;
}

/* 筛选弹窗样式 */
::v-deep .filter-dialog {
  color: #d0e0f0;
  background: rgba(20, 30, 50, 0.95) !important;
  backdrop-filter: blur(10px);
  border: 1px solid rgba(64, 158, 255, 0.5);
  border-radius: 10px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.6);

  .el-dialog__header {
    background: rgba(30, 50, 80, 0.8);
    border-bottom: 1px solid rgba(64, 158, 255, 0.3);
    padding: 15px 20px;
  }

  .el-dialog__title {
    color: #a0c0e0;
    font-size: 16px;
  }

  .el-dialog__headerbtn {
    top: 15px;

    .el-dialog__close {
      color: #a0b9d9;
      font-size: 18px;

      &:hover {
        color: #fff;
      }
    }
  }

  .el-dialog__body {
    padding: 20px;
    background: rgba(15, 30, 50, 0.85);
  }

  .el-checkbox__label {
    color: #ccc !important;
  }
}

.filter-container {
  .filter-group {
    margin-bottom: 20px;
    padding: 15px;
    background: rgba(20, 40, 65, 0.8);
    border-radius: 8px;
    border: 1px solid rgba(64, 158, 255, 0.3);

    h4 {
      color: #409eff;
      margin: 0 0 10px 0;
      font-size: 15px;
    }

    ::v-deep .el-radio-group,
    ::v-deep .el-checkbox-group {
      display: flex;
      flex-wrap: wrap;
      gap: 10px;
    }

    ::v-deep .el-radio,
    ::v-deep .el-checkbox {
      color: #d0e0f0;
      margin-right: 0;

      &__label {
        color: #d0e0f0;
        font-size: 14px;
      }
    }

    ::v-deep .el-radio__input.is-checked .el-radio__inner {
      border-color: #409eff;
      background: #409eff;
    }

    ::v-deep .el-radio__input.is-checked + .el-radio__label {
      color: #409eff;
    }

    ::v-deep .el-checkbox__input.is-checked .el-checkbox__inner {
      border-color: #409eff;
      background: #409eff;
    }

    ::v-deep .el-checkbox__input.is-checked + .el-checkbox__label {
      color: #409eff;
    }
  }
}

.action-btns {
  margin-top: 20px;
  display: flex;
  justify-content: flex-end;
  gap: 10px;

  .el-button {
    padding: 10px 20px;
    border-radius: 5px;
    transition: all 0.3s;
    background: rgba(40, 80, 130, 0.8);
    border: 1px solid rgba(64, 158, 255, 0.3);
    color: #d0e0f0;

    &:hover {
      transform: translateY(-2px);
      box-shadow: 0 2px 8px rgba(64, 158, 255, 0.3);
      background: rgba(50, 90, 140, 0.9);
      color: white;
    }

    &:active {
      transform: translateY(1px);
    }

    &.el-button--primary {
      background: rgba(64, 158, 255, 0.6);
      border-color: rgba(64, 158, 255, 0.7);

      &:hover {
        background: rgba(64, 158, 255, 0.8);
      }
    }
  }
}

/* 颜色配置弹窗样式 */
::v-deep .color-config-dialog {
  background: rgba(20, 30, 50, 0.95) !important;
  backdrop-filter: blur(10px);
  border: 1px solid rgba(64, 158, 255, 0.3);
  border-radius: 10px;
  color: #d0e0f0;

  .el-dialog__header {
    background: rgba(30, 50, 80, 0.8);
    border-bottom: 1px solid rgba(64, 158, 255, 0.3);
    cursor: move;
  }

  .el-dialog__title {
    color: #a0c0e0;
  }

  .el-dialog__body {
    padding: 20px;
    max-height: 70vh;
    overflow-y: auto;
  }
}

.color-config-container {
  padding: 10px;

  .color-by-section {
    margin-bottom: 20px;
    padding: 15px;
    background: rgba(30, 50, 80, 0.5);
    border-radius: 8px;

    h4 {
      display: inline-block;
      margin-right: 15px;
      color: #409eff;
    }

    .el-radio-group {
      display: inline-block;
    }
  }

  .color-config-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 20px;
    margin-bottom: 20px;

    .color-category {
      background: rgba(25, 40, 65, 0.7);
      border-radius: 8px;
      padding: 15px;
      border: 1px solid rgba(64, 158, 255, 0.2);

      h4 {
        margin-top: 0;
        margin-bottom: 15px;
        color: #409eff;
        border-bottom: 1px solid rgba(64, 158, 255, 0.3);
        padding-bottom: 10px;
      }

      .color-item {
        display: flex;
        align-items: center;
        margin-bottom: 12px;

        .color-label {
          width: 120px;
          color: #a0c0e0;
        }

        .color-picker-container {
          display: flex;
          align-items: center;

          .el-color-picker {
            margin-right: 10px;
          }

          .color-value {
            background: rgba(0, 0, 0, 0.3);
            padding: 2px 8px;
            border-radius: 4px;
            font-family: monospace;
          }
        }
      }
    }
  }

  .action-btns {
    text-align: right;
    padding-top: 15px;
    border-top: 1px solid rgba(64, 158, 255, 0.3);
  }
}

/* 配置弹窗样式 */
::v-deep .transfer-dialog {
  background: rgba(20, 30, 50, 0.95) !important;
  backdrop-filter: blur(10px);
  border: 1px solid rgba(64, 158, 255, 0.3);
  border-radius: 10px;
  color: #d0e0f0;

  .el-dialog__header {
    background: rgba(30, 50, 80, 0.8);
    border-bottom: 1px solid rgba(64, 158, 255, 0.3);
  }

  .el-dialog__title {
    color: #a0c0e0;
  }

  /* 配置弹窗内文字颜色 */
  .transfer-config-dialog,
  .transfer-item,
  .dialog-footer {
    color: #fff;
  }
}

.transfer-config-dialog {
  background: rgba(15, 30, 50, 0.95);
  border-radius: 8px;
  padding: 15px;

  .transfer-header {
    display: flex;
    justify-content: space-between;
    margin-bottom: 15px;
    text-align: center;

    .transfer-col {
      flex: 1;
      padding: 0 10px;

      h4 {
        color: #409eff;
        margin: 0 0 5px 0;
        font-size: 16px;
      }

      p {
        color: #a0b9d9;
        font-size: 12px;
        margin: 0;
      }
    }
  }

  .three-column-transfer {
    display: flex;
    justify-content: space-between;
    align-items: stretch;
    gap: 15px;
    margin-top: 20px;

    .transfer-column {
      flex: 1;
      height: 300px;
      border: 1px solid rgba(64, 158, 255, 0.3);
      border-radius: 6px;
      background: rgba(20, 40, 65, 0.8);
      overflow-y: auto;

      .transfer-list {
        padding: 10px;
        height: 100%;
      }

      .transfer-item {
        padding: 10px 15px;
        margin-bottom: 8px;
        border-radius: 4px;
        background: rgba(30, 60, 100, 0.5);
        cursor: pointer;
        transition: all 0.2s;
        color: #c0d0e0;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        text-align: center;

        &:hover {
          background: rgba(40, 80, 130, 0.7);
        }

        &.selected {
          background: rgba(64, 158, 255, 0.5);
          color: white;
        }
      }
    }

    .transfer-actions {
      display: flex;
      flex-direction: column;
      justify-content: center;
      min-width: 60px;

      .btn-group {
        display: flex;
        flex-direction: column;
        gap: 15px;
        align-items: center;
      }
    }
  }

  .dialog-footer {
    text-align: center;
    padding-top: 15px;
  }
}

/* 右键菜单样式 */
.cesium-context-menu {
  position: fixed;
  z-index: 10000;
  background: rgba(20, 30, 50, 0.95);
  backdrop-filter: blur(10px);
  border: 1px solid rgba(64, 158, 255, 0.5);
  border-radius: 8px;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.7);
  width: 320px;
  color: #d0e0f0;
  overflow: hidden;

  .menu-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 12px 15px;
    background: rgba(30, 50, 80, 0.8);
    border-bottom: 1px solid rgba(64, 158, 255, 0.3);

    h4 {
      margin: 0;
      color: #409eff;
      font-size: 16px;
    }

    .close-btn {
      background: none;
      border: none;
      color: #a0b9d9;
      font-size: 16px;
      cursor: pointer;
      padding: 0 5px;

      &:hover {
        color: white;
      }
    }
  }

  .menu-section {
    padding: 15px;

    h5 {
      margin-top: 0;
      margin-bottom: 12px;
      color: #409eff;
      font-size: 14px;
      display: flex;
      align-items: center;

      &::before {
        content: "";
        display: inline-block;
        width: 4px;
        height: 14px;
        background: #409eff;
        margin-right: 8px;
        border-radius: 2px;
      }
    }
  }

  .menu-divider {
    height: 1px;
    background: rgba(64, 158, 255, 0.3);
    margin: 5px 15px;
  }

  .channel-list {
    max-height: 300px;
    overflow-y: auto;
    margin: -5px;

    .channel-item {
      padding: 10px;
      margin-bottom: 8px;
      background: rgba(25, 40, 65, 0.7);
      border-radius: 6px;
      border: 1px solid rgba(64, 158, 255, 0.2);
      cursor: pointer;
      transition: all 0.3s;

      &:hover {
        background: rgba(35, 60, 95, 0.8);
        border-color: rgba(64, 158, 255, 0.5);
      }

      &:last-child {
        margin-bottom: 0;
      }
    }

    .channel-info {
      display: flex;
      align-items: center;

      .channel-name {
        flex: 1;
        margin: 0 10px;
        font-weight: 500;
        color: #a0c0e0;
      }

      .el-tag {
        height: 22px;
        line-height: 20px;
        margin-right: 8px;
      }

      .channel-arrow {
        color: #a0c0e0;
        font-size: 14px;
      }
    }
  }

  .action-buttons {
    display: flex;
    justify-content: space-between;
    gap: 10px;

    .el-button {
      flex: 1;
    }
  }
}

/* 通道操作菜单样式 */
.channel-operation-menu {
  position: fixed;
  z-index: 10001;
  background: rgba(20, 30, 50, 0.95);
  backdrop-filter: blur(10px);
  border: 1px solid rgba(64, 158, 255, 0.5);
  border-radius: 8px;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.7);
  width: 280px;
  color: #d0e0f0;
  overflow: hidden;

  .menu-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 12px 15px;
    background: rgba(30, 50, 80, 0.8);
    border-bottom: 1px solid rgba(64, 158, 255, 0.3);

    h4 {
      margin: 0;
      color: #409eff;
      font-size: 16px;
    }

    .close-btn {
      background: none;
      border: none;
      color: #a0b9d9;
      font-size: 16px;
      cursor: pointer;
      padding: 0 5px;

      &:hover {
        color: white;
      }
    }
  }

  .menu-section {
    padding: 10px;
  }

  .menu-divider {
    height: 1px;
    background: rgba(64, 158, 255, 0.3);
    margin: 5px 15px;
  }

  .menu-btn {
    display: block;
    width: 100%;
    margin-bottom: 8px;
    text-align: left;
    padding: 10px 15px;
    background: rgba(35, 55, 85, 0.7);
    border: none;
    border-radius: 6px;
    color: #d0e0f0;
    cursor: pointer;
    transition: all 0.3s;

    i {
      margin-right: 8px;
      width: 20px;
      text-align: center;
    }

    &:hover {
      background: rgba(45, 75, 115, 0.8);
      transform: translateX(5px);
    }

    &:last-child {
      margin-bottom: 0;
    }
  }

  .action-buttons {
    display: flex;
    justify-content: space-between;
    padding: 10px;
    gap: 10px;

    .el-button {
      flex: 1;
    }
  }
}

/* 样式配置 */
::v-deep .style-config-dialog {
  background: rgba(20, 30, 50, 0.95) !important;
  backdrop-filter: blur(10px);
  border: 1px solid rgba(64, 158, 255, 0.5);
  border-radius: 10px;
  color: #d0e0f0;

  .el-dialog__title {
    color: #409eff;
    font-size: 16px;
  }
  .el-dialog__header {
    background: rgba(30, 50, 80, 0.8);
    border-bottom: 1px solid rgba(64, 158, 255, 0.3);
    cursor: move;
  }

  .el-dialog__body {
    padding: 20px;
    background: rgba(15, 30, 50, 0.85);
  }
}

.style-config {
  padding: 15px;

  .config-item {
    display: flex;
    align-items: center;
    margin-bottom: 20px;

    label {
      width: 100px;
      color: #606266;
      font-size: 14px;
    }

    .el-input-number,
    .el-color-picker {
      flex: 1;
    }
  }
}
/* 通道列表样式 */
.channel-item.ionosphere {
  border-left: 3px solid #9c27b0;
}

/* 频率控制样式 */
.menu-section .el-checkbox {
  display: block;
  margin: 8px 0;
}
/* 添加频率标签样式 */
.frequency-checkbox {
  display: block;
  padding: 10px 15px;
  margin-top: 8px;
  background: rgba(35, 55, 85, 0.7);
  border-radius: 6px;
  color: #d0e0f0;
  transition: all 0.3s;

  &:hover {
    background: rgba(45, 75, 115, 0.8);
  }

  ::v-deep .el-checkbox__label {
    color: #d0e0f0;
    font-size: 14px;
  }
}
</style>
